Nette\Database join pomocí cizích klíču

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Seith
Člen | 24
+
0
-

Už se s tím patlám celkem dlouho, vysvětlí mi někdo, jak rozchodím přes DiscoveredReflection tohle například?

Mám 2 tabulky, user a token, user obsahuje sloupec verify_id, který je cizím klíčem na token.id. Jde psát něco ve smyslu?:

$user = $this->getTable()->where(id, 5);
if ($user->verify->hash == '...') ...
jtousek
Člen | 951
+
0
-

Ano, ale za to where patří ještě ->fetch(). Anebo místo where použij ->get(5).

Seith
Člen | 24
+
0
-

Ano, na tohle jsem zapomněl v příspěvku co jsem psal, jen abych nastínil, co potřebuji. Fetch tam mám, v $user je instance třídy Nette\Database\Table\ActiveRow. Ale pokud zavolám verify, vyhodí mi to vyjímku Cannot read an undeclared column „verify“.

Seith
Člen | 24
+
0
-

Avšak pro doplnění, pokud dumpnu verify_id, je tam hodnota id a vše funguje, pokud dumpnu pouze verify, vyhazuje to vyjímku.

hrach
Člen | 1834
+
0
-

struktura db? sql dump? mas inno db?

Seith
Člen | 24
+
0
-
CREATE TABLE `token` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `hash` char(40) COLLATE utf8_czech_ci NOT NULL,
  `validity` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `hash` (`hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;


CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(255) COLLATE utf8_czech_ci NOT NULL,
  `email` varchar(255) COLLATE utf8_czech_ci NOT NULL,
  `password` char(40) COLLATE utf8_czech_ci NOT NULL,
  `role` enum('registered','admin') COLLATE utf8_czech_ci NOT NULL,
  `verified_id` int(10) unsigned DEFAULT NULL,
  `forgottenPassword_id` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `login` (`username`),
  UNIQUE KEY `email` (`email`),
  KEY `verified_id` (`verified_id`),
  KEY `forgottenPassword_id` (`forgottenPassword_id`),
  CONSTRAINT `user_ibfk_1` FOREIGN KEY (`verified_id`) REFERENCES `token` (`id`),
  CONSTRAINT `user_ibfk_2` FOREIGN KEY (`forgottenPassword_id`) REFERENCES `token` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
jtousek
Člen | 951
+
0
-

verified_id != verify_id

Seith
Člen | 24
+
0
-

ano, já vím… když jsem psal první příspěvky, neměl jsem po ruce databázi, ve skriptech je samozřejmě verified_id, jinak by nefungoval dump

Seith
Člen | 24
+
0
-

ještě pro doplění:

$user = $this->findOneBy('email', $email); //vrací ActiveRow

dump($user->verified_id); //funguje, vypíše id
dump($user->verified); //Cannot read an undeclared column "verified"

config:

common:
    nette:
        database:
            default:
                dsn: 'mysql:host=127.0.0.1;dbname=databaze'
                user: root
                password:
                reflection: discovered

Editoval Seith (19. 9. 2012 21:02)

Seith
Člen | 24
+
0
-

Kdyby měl někdy náhodou někdo podobnej problém, stačí smazat cache… Že mě to ale napadne až druhý den, co se dá dělat. Jenom malinkatý dotaz, nemaže se cache při vývojovém režimu pokaždém spuštění?

jtousek
Člen | 951
+
0
-

Ne nemaže, to bys totiž při vývoji čekal na každý požadavek docela dlouho. Lze to nastavit tím, že použiješ MemoryStorage.

hrach
Člen | 1834
+
0
-

Hm, asi je tam bud, musim se na to podivat, to preinvalidovani by melo jet samo,kdyz se nic nenajde. :) diky

o5
Člen | 416
+
0
-

Ahoj, kde delam chybu?

foreach ($connection->table('user') as $item) {
	dump($item->related('country', 'country_code')->title);
	//Cannot read an undeclared property Nette\Database\Table\GroupedSelection::$title.
}
//sqlite3

CREATE TABLE "country" (
  "code" text NOT NULL,
  "title" text NOT NULL
);

CREATE TABLE "user" (
  "id" integer NULL PRIMARY KEY AUTOINCREMENT,
  "firstname" text NOT NULL,
  "country_code" text NOT NULL,
   FOREIGN KEY(country_code) REFERENCES country(code) ON DELETE CASCADE ON UPDATE CASCADE
);
PHP 5.3.15
Nette Framework 2.0.6 (revision 6a33aa6 released on 2012-10-01)

Editoval o5 (28. 11. 2012 11:03)

hrach
Člen | 1834
+
0
-

tabulka country musi mit primarni klic.

o5
Člen | 416
+
0
-

Tak jsem asi natvrdlej, i s primarnim country.code stejna chyba :/ Tady je db http://goo.gl/7jpsE

Editoval o5 (28. 11. 2012 13:05)

vvoody
Člen | 910
+
0
-

Zmaž cache a použi ref namiesto related.

o5
Člen | 416
+
0
-

vvoody wrote:

Zmaž cache a použi ref namiesto related.

To strilis od boku? Ti tri lide co si tu db stahli taky nevi, nebo jim to fungovalo?

Editoval o5 (28. 11. 2012 21:24)

vvoody
Člen | 910
+
0
-

Nie. Skúsil si to?

$user->ref('country', 'country_code')->title;

s defaultnou reflection a štruktúrou ktorú máš by ti malo fungovať aj

$user->country->title;

ale za to už ruku do ohňa nedám.

enumag
Člen | 2118
+
0
-

o5: Jistěže nestřílí. Máš tam vazbu 1:1, pro tu slouží ref. Metoda related, kterou jsi chybně použil slouží na vazbu 1:N, což je něco úplně jiného.

mildabre
Člen | 62
+
0
-

Je to v podstatě jenom formalita, ale i v tabulce country bych pro primární klíč použil třetí sloupec id. Cizí klíč v tabulce user by potom byl country_id místo country_code. Úplná formalita to ale není, zkus si představit třeba takový scénář z reálného života, kdy se třeba Česko přejmenuje na Kocourkov a country code z cs na kc a uživatelé linkovaní na country_code Česka by potřebovali změnit country_code. To by znamenalo přepisovat všechny uživatele v tabulce user. Když se použije id, stačí přepsat jeden záznam v tabulce country.

Editoval mildabre (11. 12. 2012 21:00)