Přistupování k cizím tabulkám přes cizí klíč, nikoli přes název sloupce

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

Ahoj.
Četl jsem téma https://forum.nette.org/…azvu-sloupce#… kde se řeší stejný problém. David Grudl tenkrát napsal, že to zatím není implementované. Pročítal jsem diskuzi dál, ale když se začali věci jako DatabaseReflection, už jsem se úplně ztratil a diskuze šla mimo mě. Chtěl bych Vás tedy požádat, jestli by někdo nemohl nějak ve stručnosti přetlumočit, jak to tedy funguje, když chci k tabulkám přistupovat přes cizí klíče:

$n = $db->table('news')->where('id', $id)->limit(1);
echo $n->author->username;

kde sloupec author z tabulky news odkazuje na tabulku users
Děkuji za odpovědi

hrach
Člen | 1838
+
0
-
  1. vyše zmíněný příklad ti sice vytáhne jeden záznam, ale dostaneš ho v poli, tzn. když chceš jeden záznam, použij get()
    $n = $db->table('news')->get($id);
  2. příště si to pořádně přečti :P
  3. máš dvě možnosti, buď budeš používat databázi foreign keys a pak můžeš při vytvoření spojení nastavit DIscoveredReflection, která ti automaticky zjistí, že author→ vede na tabulku users.
    $connection->setDatabaseReflection(new Nette\Database\Reflection\DiscoveredReflection);
  4. nebo jednoduše to řekneš nette datbase ty, přes jakou vazbu si to má vzít:
    $n->ref('users', 'author_id')->username
Neas
Člen | 43
+
0
-

A která z těchto dvou možností pracuje rychleji?

hrach
Člen | 1838
+
0
-

prakticky žádná (u c) je cache zbytek je zanedbatelny), teoreticky d)

Neas
Člen | 43
+
0
-

Zkusil jsem první možnost, funguje, ale nerozumím jedné věci: podle debug baru v pravém dolním rohu, se při načtení stránky provedlo celkem 5 SQL dotazů, které zabraly něco přes 10ms. Z nich navíc jeden je

SHOW FULL COLUMNS
FROM `forum_users`

který vrací 76 řádků s uživateli, z nichž 75 se nevyužije. Myslel jsem, že DatabaseReflection a vůbec foreign keys obecně existují kvůli zefektivnění práce s databází. Dělám něco špatně, nebo sem něco špatně pochopil?
PS: stránka má za úkol jen vypsat poslední novinku a jméno a id jejího autora.

Jan Jakeš
Člen | 177
+
0
-

Nevím, kde jsi přišel k tomu, še SHOW FULL COLUMNS vrací řádky s uživateli (je snad column řádek?). Tento příkaz jen zjišťuje podobu databázové tabulky (jaké má sloupce, klíče, atd.) při prvním načtení, podruhé už budou informace známé z cache. Nevím, jaké tam máš další dotazy, ale nejspíš tam bude prozkoumání obou tabulek a pak jeden dotaz do každé tabulky zvlášť (místo JOINu). Pokud stránku znovu načteš, měly by být položeny jen dva velmi rychlé dotazy.

Neas
Člen | 43
+
0
-

rozumím, děkuji za vysvětlení. Avšak po znovu načtení stránky se všechny dotazy provedly znovu. Chápu tedy dobře, že se jedná pouze o špatné nastavení xamppu a na hostingu se to spraví?

Jan Jakeš
Člen | 177
+
0
-

Aha, z nějakého důvodu ti asi nefunguje cache. Podívej se do temp/cache, jestli je tam nějaká podsložka Nette.Database..., případně sem postni, jak máš cache nastavenou nebo config.neon. Jseš na Windows nebo Linux?

Neas
Člen | 43
+
0
-

Neon jsem jen okopíroval z nějakého example po stažení nette balíku a upravil pouze příslušné třídy, zmínka o cache tam není, pouze v bootstrap.php mám:

$configurator->setTempDirectory(__DIR__ . '/../../temp');

zkoušel jsem teď do neonu napsat:

	services:
		cacheStorage:
			class: Nette\Caching\Storages\MemcachedStorage

ale vyhazuje mi to: PHP extension ‚memcache‘ is not loaded
jinak v temp/cache zmínka o Nette.Database neni a používám win xp.

hrach
Člen | 1838
+
0
-

ehm, ty mi tu řešíš výkonost a pak mi tu kopíruješ zdrojáky aniž by sis uvědomil, že na localhostu nemáš nainstalovaný memcache?

Cache storage se musí nette connection nastavit:
https://api.nette.org/…nection.html#…

Neas
Člen | 43
+
0
-

tak jsem do neonu po přečtení několika článků vepsal:

services:
	cacheStorage:
		class: Nette\Caching\Storages\FileStorage(%tempDir%/cache)

	database:
		class: Nette\Database\Connection('mysql:host=localhost;dbname=rpg2heaven', 'root', '')
		setup:
					- setCacheStorage(@cacheStorage)

ve složce temp/cache se teď po načtení stránky objevuje podadresář _Nette.Database.4ebae46bd652b69fb4a7cc9fa3e930e6 avšak na stránce se stále provádí všech 5 dotazů. Co tedy může ještě být špatně?

Editoval Neas (15. 1. 2012 21:20)

Neas
Člen | 43
+
0
-

update: nakonec se mi povedlo cache zprovoznit, stačilo do configu pod db přidat řádek (přesunuto z modelu, kde bylo nevhodně umístěno a odkaz na cacheStorage byl null):

- setDatabaseReflection(Nette\Database\Reflection\DiscoveredReflection(@cacheStorage))

jen bych měl k věci poslední dotaz: k čemu slouží řádek:

- setCacheStorage(@cacheStorage)

? měl jsem podle názvu za to, že právě tento řádek má na starosti cachování databáze, avšak aplikace funguje (vykonává 2 rychlé dotazy namísto 5ti) dobře, i když tento řádek zakomentuju, proto mě to zajímá.
Děkuji za odpovědi

hrach
Člen | 1838
+
0
-

Jde to to, ze Connection a DiscoveredReflection jsou dve entity, ktere pouzivaji cache a kazda muzou chtit pouzivat jinou cache (pripadne ji nepouzivat). Proto tedy setCacheStorage nastavuje cache strage pro Connection, kdezto druha cache storage v conctrucotoru DiscoveredReflection ji, prekvapive, nastavuje DircoveredReflection.

Omlouvam se za spatnou odpoved o prispevek vys…

ViPEr*CZ*
Člen | 817
+
0
-

Takhle to má být jestli se nepletu:

database:
	class: Nette\Database\Connection
	arguments: ['mysql:host=localhost;dbname=****jmeno_db*****', '****jmeno****', '****heslo****']
	setup:
		- setCacheStorage()
		- setDatabaseReflection( Nette\Database\Reflection\DiscoveredReflection() )

Když ten řádek zakomentujete, tak to nepoužívá cache jestli se opět nepletu.
A plus ještě co píše hrach … ;-)

Editoval ViPEr*CZ* (16. 1. 2012 17:47)

Neas
Člen | 43
+
0
-

Už rozumím, děkuji za objasnění.

Editoval Neas (16. 1. 2012 18:14)

Neas
Člen | 43
+
0
-

Narazil jsem na další menší úskalí se spojováním tabulek s cizími klíči a DatabaseReflection. Nechci kvůli tomu zakládat nové téma, jelikož se podstata problému zase tolik nezměnila. Předem říkám, že jsem s cizími klíči nikdy předtím neměl tu čest, takže se omlouvám za případný hloupý dotaz, ale: je-li nastaven cizí klíč, nejde smazat záznam z tabulky, na kterou odkazuje. Což ale znamená, že budu-li používat cizí klíče jako dosud při testech, nebudu moci smazat například uživatele, který přidal nějaký příspěvek (v tabulce příspěvky odkazuji cizím klíčem na jméno autora). Můj dotaz proto zní: jde nastavit cizí klíč tak, aby se daly měnit/mazat i záznamy, na které odkazuje (a v případě neexistence záznamu například vrátit namísto id autora NULL nebo tak), a pokud ne, umožňuje Nette nějaký výběr se stejnou podstatou bez použití cizího klíče?

Děkuji

Editoval Neas (19. 1. 2012 23:11)

hrach
Člen | 1838
+
0
-

V nette je vychozi ConventionalReflection, ktere cizi klice nepouziva.
Ohledne mazani zaznamu: https://cs.wikipedia.org/…%C3%AD%C4%8D