Jak fungují v nette\database foreign keys

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

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)

hrach
Člen | 1838
+
0
-

„Konvence“ vypada v poradku. Ale ocividne pouzivas ConventionalReflection, kde by teda konvence mela byt, ze tabulky se jmenuji v jednotnem cisle. Doporucuji ale pouzit DiscoveredReflection.

Šaman
Člen | 2666
+
0
-

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
+
0
-

@Š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á na obsahuje „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)

vvoody
Člen | 910
+
0
-
  • DiscoveredReflection najde sloupec s co nejkratším názvem který obsahuje „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.
enumag
Člen | 2118
+
0
-

@vvoody: Jo, máš pravdu. Tohle i pro mne byla novinka, díky. ;-)

Šaman
Člen | 2666
+
0
-

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
+
0
-
  • 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
+
0
-

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)

enumag
Člen | 2118
+
0
-

@danielseek: Existuje mnohem jednodušší způsob.

Šaman
Člen | 2666
+
0
-

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
+
0
-

@Š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)

Šaman
Člen | 2666
+
0
-

Tak to se nám to zase trochu zamotává..
A to už jsem byl přesvědčený, že je čas udělat Dibi pá pá. Ještě ho nakonec budu prosit, aby se ke mě do projektů vrátil :)

enumag
Člen | 2118
+
0
-

@Š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)

vvoody
Člen | 910
+
0
-

EDIT: Mimochodem i pokud používáš ConventionalReflection tak stále máš metodu ref, která nepoužívá žádnou reflexi ak uvedieš aj druhý parameter. Vždy tedy existuje možnost jak se třeba k tomu autorovi dostat, jen to bude mít trochu delší zápis.

Šaman
Člen | 2666
+
0
-

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
+
0
-

@vvoody: Thx again! ;-)

@Šaman: Ještě koukám do zdrojáku, SqliteDriver cizí klíče umí taky, z ostatních už opravdu žádný.

hrach
Člen | 1838
+
0
-

Ad Sqlite:

  • pouze verze 3.
  • je tam bug :D
enumag
Člen | 2118
+
0
-

@hrach: Ten fix v Nette ještě není? :-D Máme alespoň PR nebo ani to ne?

hrach
Člen | 1838
+
0
-

Už je to fixle :D

enumag
Člen | 2118
+
0
-

Viděl jsem, díky. ;-)