Jak fungují v nette\database foreign keys
- danielseek
- Člen | 42
Ahoj,
jaký je způsob určování cílové tabulky?
Mám sql tabulku articles->user_id odkazující na users->id a nette mi
neustále hází
exception: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'drifting.user' doesn't exist
Neměl by se název cílové tabulky, tedy users odvodit z cizího klíče? Musím změnit konvenci?
php kód
{$article->user->name}
Editoval danielseek (3. 3. 2013 22:25)
- Šaman
- Člen | 2666
Můžeš nás odkázat na nějaký materiál, nebo tohle trochu rozvést?
Používám konvenci z dokumentace, ale některé věci bych si rád upravil,
protože jsem zvyklý na jinou konvenci a stále musím přepisovat názvy
kličů když vytvářím db. (Na jednotné číslo jsem si zvykl, ušetří
nám to problémy s nepravidelnými množnými čísly, ale místo
user_id
bych raději používal ‚id_user‘.)
- enumag
- Člen | 2118
@Šaman: Materiál k tomu pokud vím neexistuje, ale jednu věc ti řeknu. Vězměme v úvahu tento kód:
$article->user->name;
Jak se najde správný user
?
- ConventionalReflection dle zadané konvence (kterou můžeš změnit) vydedukuje cílovou tabulku (ve výchozím případě %s, tedy user) a propojovací sloupec (ve výchozím případě %s_id, tedy user_id).
- DiscoveredReflection najde sloupec s co nejkratším názvem který
začíná naobsahuje „user“ a je cizím klíčem (nezáleží na jakou tabulku). Z této tabulky vytáhne řádek který má primární klíč shodný s hodnotou v tom nalezeném sloupci.
Doufám, že se to dá pochopit, nevím zda jsem to napsal dost srozumitelně.
@hrach: Prosím oprav mne pokud jsem řekl nějakou pitomost. ;-) Ale snad ne.
Editoval enumag (3. 3. 2013 23:20)
- Šaman
- Člen | 2666
Ee.. jestli jsem to pochopil to nevím, ale myslím si, že nevím.
Když mám tabulku 'user'
, ale cizí klíč je
'author_id'
, tak:
ConventionalReflection
si s tím poradí jak? Tabulka'author'
neexistuje.- takže to zkusí dohledat
DiscoveredReflection
? Jak vlastně zjistím, která reflexe se použije?
- enumag
- Člen | 2118
- ConventionalReflection si s tím jednoduše neporadí (afaik)
- DiscoveredReflection nemá problém
Tohle je jedna z demencí NDB (imho). NetteExtension jako výchozí vyrábí Discovered, ale Connection jako výchozí vyrábí Conventional. Tzn. pokud NDB používáš přes NetteExtension, je výchozí discovered. V ostatních případech je výchozí Conventional.
Jinak si můžeš v debugbaru najít tu službu connection a na reflexi se přímo podívat.
Editoval enumag (3. 3. 2013 23:42)
- danielseek
- Člen | 42
Kdyby někdo stejně jako já nevěděl, kde se to nastavuje, tak mu rád ušetřím šťourání se v kódu nette. Opravte mne pokud se mýlím:
services:
dbReflection: Nette\Database\Reflection\DiscoveredReflection
database:
class: Nette\Database\Connection(
'%db.driver%:host=%db.host%;dbname=%db.dbname%',
%db.user%,
%db.password%
)
setup:
- setDatabaseReflection(@dbReflection)
Editoval danielseek (3. 3. 2013 23:43)
- Šaman
- Člen | 2666
Díky, používám extension, takže DiscoveredReflection
a
skutečně když změním 'author_id'
na 'id_author'
,
tak to funguje. Jenom z toho trochu cítím magii.
K čemu je tedy dobrý 'ConventionalReflection'
? Teda kromě
toho, že je nemagický.. Cizí klíč se jen málokdy jmenuje stejně, jako
cílová tabulka, resp. v každém projektu bude na 99% cizí klíč, který se
tak nejmenuje.
- enumag
- Člen | 2118
@Šaman: Pokud máš jinou databázi než MySQL nebo Postgres tak DiscoveredReflection nejde použít protože nettí driver si neumí zjistit cizí klíče. Totéž pokud máš MySQL, ale tabulky jsou v MyISAM. V těchto případech je ConventionalRelfection jediná možnost. Pokud ti nestačí, musíš si napsat vlastní reflexi.
Editoval enumag (4. 3. 2013 0:04)
- enumag
- Člen | 2118
@Šaman: Chápu. :-D V podstatě je to takhle. Cenou za optimální používání NDB je nutnost použít MySQL (+ InnoDB) anebo Postgres, případně by ještě měla běhat MariaDB. Jsi-li ochoten tuto daň zaplatit, vítej ve světě NDB. Jinak zůstaň u dibi nebo přejdi na doktrínu. :-)
Na webu je MySQL nejčastější a profesionální aplikace stejně potřebuje transakce, tedy InnoDB. Menší skupina webů používá Postgres, kde je vše taky ok. Aplikaci běžící na něčem jiném jsem osobně viděl leda z rychlíku. ;-) Samozřejmě tvé zkušenosti mohou být úplně jiné.
Jo a kdybys dopsal podporu pro čtení klíčů do nějakého dalšího driveru (např. MSSQL pro by to mělo jít), komunita to určitě uvítá. Pak by ti discovered reflexe fungovala.
EDIT: Mimochodem i pokud používáš ConventionalReflection tak stále máš metodu ref, která nepoužívá žádnou reflexi pokud uvedeš i druhý parametr. Vždy tedy existuje možnost jak se třeba k tomu autorovi dostat, jen to bude mít trochu delší zápis.
Editoval enumag (4. 3. 2013 0:32)
- Šaman
- Člen | 2666
Jasný. Taky jsem se zatím setkal jen s migrací z MySQL na Postgres,
používat to zatím budu, než se s tím seznámím dokonale a pak se
uvidí.
Jen na přednáškách chválím databázové vrstvy od Davida s tím, že
změnou driveru je bez nutnosti přepsat kód možnost migrovat mezi db. Zrovna
ten MsSQL jsem (naštěstí jen z rychlíku) potkal. Ale teď mi to prakticky
nevadí, jen jsem rád, že o tom vím.
- enumag
- Člen | 2118
@vvoody: Thx again! ;-)
@Šaman: Ještě koukám do zdrojáku, SqliteDriver cizí klíče umí taky, z ostatních už opravdu žádný.