Magické odkazovanie cudzími kľúčmi
- sabrx
- Člen | 47
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
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
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
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
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)