Magické odkazovanie cudzími kľúčmi

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

Zdravím,

Chcem poprosiť niekoho fundovaného o vysvetlenie, ako vlastne funguje prísup k iným tabuľkám cez cudzie kľúče. V Quickstarte sa píše:

Další zajímavostí je konstrukce $task->user->name. Jak již bylo řešeno v předchozí části věnované databázi, sloupec user_id považuje databázová vrstva za odkaz na tabulku user. Díky tomu se pak můžeme takto odkázat na tabulku user.

Najprv som si myslel, že odkazovanie uvedením user je možné, pretože je to súčasne názov tabuľky, ale ono to funguje aj po zmene názvu tabuľky, napr. z user na st_user. Po zmene stále funguje výraz $task->user->name, namiesto $task->st_user->name. Zaujíma ma teda, na základe čoho databázová vrstva považuje nejaký stĺpec za odkaz na inú tabuľku, ak nie na základe názvu tabuľky. Na fóre som našiel len niečo o konvenciách, ale nejakú presnú odpoveď nie. Ďakujem za pomoc!

frosty22
Člen | 373
+
0
-

Hezké, že :) To co jsi popsal jako první čili přes součást názvu, tak to funguje v případě, že se používá ConventionalReflection, ale ve výchozím stavu a v tvém případě je použit DiscoveredReflection, který se podívá do schémat databáze a nakešuje si, jak jsou propojené tabulky a následně už ví, jak na to :) Konkrétní query například pro MySQL pak zde v driveru.

sabrx
Člen | 47
+
0
-

Vďaka za odpoveď, ale stále nechápem, z čoho sa odvodí ten prístup cez user, keď tabuľka má názov st_user a stĺpec user_id.

sabrx
Člen | 47
+
0
-

Tu je môj konkrétny problém. Mám tabuľku tz_cities, v ktorej sú uložené časové zóny. V tabuľke st_user je stĺpec tz_offset, ktorý je cudzím kľúčom a odkazuje na tabuľku tz_cities. Ako zistím, cez čo sa môžem odkazovať v Nette z tabuľky user do tabuľky tz_cities?

Toto som skúšal:

$user->ref('tz_cities')->city_code;
$user->tz_cities->city_code;

Obe s chybou PDOException

No reference found for $st_user->tz_cities.

sabrx
Člen | 47
+
0
-

Takže podarilo sa mi to vyriešiť. V tabuľke st_user som zmenil názov tz_offset na tz_city_id, ďalej názov tabuľky tz_cities na tz_city (jednotné číslo pri všetkých tabuľkách), a už to funguje.

$user->tz_city->city_code

Znamená to teda, že Nette hľadá v názvoch stĺpcov názov tabuľky, a pri zhode takýto stĺpec považuje za odkaz na príslušnú tabuľku?

vvoody
Člen | 910
+
0
-

Dúfam že nepopíšem nejaké somariny, vychádzam z toho čo som pochopil z aktuálneho kódu na githube.

Na začiatok pre ujasnenie, je si treba uvedomiť dve veci. Ta prvá je, že ak budeš volať ref s obomi parametrami,

$user->ref('tz_cities','tz_offset')->city_code;
// pripadne po uprave ktoru si spravil
$user->ref('tz_city','tz_city_id')->city_code;

tak nikdy sa žiadny reflection k slovu nedostane. Úlohou reflection je práve uhádnuť $user->ref($tieto,$dva) parametre, ak toto volanie s obomi parametrami nepoužijeme.

A druhá vec :) ako si nastaviť reflecion, ktorý sa má použiť? Jednoducho v configu v sekcii Nette.

Ďalej zopár príkladov k jednotlivých implementáciám reflection:

Conventional:

Conventional zvolí FK ako názov tabuľky (na ktorú FK smeruje) s príponou _id. Názov tabuľky kam FK smeruje sa berie priamo ako volaná property nad ActiveRow
(čiže tz_cities a tz_city v nasledujúcich príkladoch).

$user->tz_cities;
// je ako by si zavolal
$user->ref('tz_cities','tz_cities_id');	// v tvojom prípade neprejde

po úprave štruktúry ktorú si v poslednom poste uviedol
tz_cities ⇒ tz_city,
st_user.tz_offset na st_user.tz_city_id

$user->tz_city;
// je ako by si zavolal
$user->ref('tz_city','tz_city_id'); // tu už by to malo fungovať

Discovered:

Predpokladám že maš nastavene FK v db, pri tejto reflecion to je nevyhnutné.
Discovered prehľadáva všetky zadefinované FK vo všetkých tabuľkách, pričom názov FK musí obsahovať volanú property (v nasledujúcom príklade tz_cities) a súčasne FK musí ukazovať na PK tabuľky tz_cities(tz_city). Taký FK v tvojom prípade neexistoval, dokial si neupravil štruktúru.

$user->tz_cities;
// žiadny FK obsahujúci tz_cities neexistuje, preto ti vybehla exception

// nasledovné volania by mali fungovať
$user->offset;
$user->tz_off;
// alebo iný názov property obsiahnutý v nazve FK (tz_offset)
// čiže to je ako by si zavolal
$user->ref('tz_cities','tz_offset');

analogicky po úprave štruktúry ktorú si v poslednom poste uviedol
tz_cities ⇒ tz_city,
st_user.tz_offset na st_user.tz_city_id

$user->tz_city;
// toto ti začalo fungovať kedže 'tz_city' je časť názvu FK 'tz_city_id'
// takže fungovať by malo aj
$user->tz_ci;
// atď
// je to ako by si zavolal
$user->ref('tz_city','tz_city_id');

Dúfam že som ťa ešte viac nedomotal :)

Editoval vvoody (15. 10. 2012 20:04)

sabrx
Člen | 47
+
0
-

Presne taketo vysvetlenie som potreboval, uz to chapem omnoho lepsie, vdaka vvoody!

Pozn.: nemas tam chybu v casti „a súčasne FK musí ukazovať na PK tabuľky st_user“? Skor FK musí ukazovat na PK tabulky tz_cities (resp. tz_city), ci nie?

enumag
Člen | 2118
+
0
-

@vvoody: Myslím, že $user->tz_city_id; vrátí přímo to ID, kdežto $user->tz_city; a $user->tz_ci; vrátí ActiveRow. Není to tedy přesně totéž.

vvoody
Člen | 910
+
0
-

enumag a sabrx napsal(a):

Správne, presne tohoto som sa bál, že napíšem takéto somariny. :D idem opravit

Stic
Člen | 28
+
0
-

@vvoody
Super vysvetlene, skoda ze to nie je nikde v dokumentacii, trvalo mi 2 dni kym som co to precital a preklikal som sa az sem :)

vvoody
Člen | 910
+
0
-

ďakujem ^_^ mal som slabú chvíľku (nebol som lenivý) tak som sa to pokúsil podrobnejšie opísať