Přistupování k cizím tabulkám přes cizí klíč, nikoli přes název sloupce
- Neas
- Člen | 43
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
- 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);
- příště si to pořádně přečti :P
- 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);
- 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
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
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
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
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
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
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
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
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
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
V nette je vychozi ConventionalReflection, ktere cizi klice nepouziva.
Ohledne mazani zaznamu: https://cs.wikipedia.org/…%C3%AD%C4%8D