Nette\Database chyba v případě vazební tabulky s dvou-sloupcovým primárním klíčem
- duke
- Člen | 650
Mám následující kód:
Při prvním spuštění správně vydumpuje:
"PHP" (3)
"MySQL" (5)
Při následném spuštění (tj. s vygenerovanou cache) už nevydumpuje nic.
Schema databáze je z NotORM balíčku – soubor tests\software.sql.
Pokud upravím tabulku application_tag tak, že ji přidám sloupec id, ze kterého udělám primární klíč, vše funguje, jak má.
- duke
- Člen | 650
Procházení samo (bez cache) funguje (proto zřejmě projde i ten test). Nefunguje to až s použitím cache (tj. v případě opakovaného requestu).
- PHP: 5.3.8
- DB: MySQL 5.1.58
- Cache: výchozí (Nette\Caching\Cache, Nette\Caching\Storages\FileStorage)
- Nette: 2.1-dev
Editoval duke (27. 2. 2012 18:34)
- Aearsis
- Člen | 57
Potvrzuju chybu, Mysql 5.1.61, Nette 2.0 – jde o to, že v ActiveRow se
v ->access
dá do id pole $this->data
, a pak se
zavolá offsetGet s polem, což zůstalo možná z NotORM, který tohle
přechroustá, Database ale ne – přímo vrací
$this->data[$key]
, což skončí Illegal offset type
warningem.
- hrach
- Člen | 1840
Divné, je na to test:
https://github.com/…e.cache.phpt#L41
Zitra odjizdim na 2dny, bohuzel se k tomu nedostanu driv nez v patek.
- hrach
- Člen | 1840
Tento kod:
mi funguje i při zapnutí cache. Jediný rozdíl mám pak v pořadá položek v $tags, ale vazby title a tag->name jsou správně.
Ohledně volání
tak to určitě není věřejně podporované, nicméně mně také funguje. Nevím, která cache ti v danou chvíli nemá fungovat.
Jsem z toho jelen.
Editoval hrach (3. 3. 2012 14:35)
- Honza Marek
- Člen | 1664
Ahoj, posílám nějaký kód pro reprodukci chyby.
Poprvý to vypíše kategorii u obou, při druhém přístupu jen u druhého článku.
- duke
- Člen | 650
Zkoušel jsem trochu experimentovat a ačkoliv nemám zcela přehled nad kódem NDB, mám za to, že problém je v tom, že se do cache neukládá informace o tom, že tabulka book_tag nemá jednosloupcový primární klíč (naopak se tam později nějak – nevím jak – dostane nesprávná informace: sloupec tag_id).
Jako řešení mi fungovalo nahradit v souboru Nette\Database\Reflection\DiscoveredReflection.php kód na řádku 91:
kódem:
Záměrně jsem použil ''
místo NULL
, kvůli
výše použitému isset
. Netestoval jsem ale, zda to neporuší
něco jiného, takže to berte spíš jako nasměrování, než jako hotové
řešení.
- David Růžička
- Člen | 43
Potvrzuji, že mám také problém s tabulkou se dvěma primárními klíči. Projevuje se jen když mám prázdnou keš, pak stačí obnovit stránku a vše začne fungovat.
- OscarHanzely
- Člen | 7
Potvrzuji puvodni chybu stale aktivni i po vice nez roce !
Mam takoveto parametry:
Nette 2.0.7
PHP 5.4.3
MySql 5.5.24
Cache: výchozí
Mam demonstracni schema, kde je vztah M:N pres vazebni tabulku s indexem pres dva sloupce. Zatim nemam projekt, takze tohle je obdoba toho book-book_tag-tag. Napadlo me to jako jednoduche schema user-user_rights_binding-user_rights. Chtel jsem si vyzkouset totoiz praci s Nette\Database
Vyber skrze tabulky jsem zkousel dle prikladu pres (vybiram popisky prav k uzivateli):
Skousel jsem nekolim variant a pri prvnim spusteni to hlasilo:
PDOException
No reference found for $user_rights_binding->
a obcas kdyz jsem zakomentoval spatny radek Nette si udelalo indexy pres fk
najednou, tak pak uz furt hlasi:
Warning
Illegal offset type na stejnych mistech kodu.
Slo to pak az do
...\libs\Nette\Database\Table\ActiveRow.php:244
a finalne to kleklo na:
...\libs\Nette\Database\Table\ActiveRow.php:289
Jak se mam tedy dostat pres vazebni tabulku se dvema FK na data ? Podotykam, ze pridani bezvyznamneho primary key do vazebni tabulky prolbem nevyresilo, jen se to pak snazilo pres nej navazat na tabulku user_rights a uplne ignorovalo i to related() :(
Jako zacatecnik v Nette jsem tyto slozite postupy jinak uz nenasel popsane a dost me to odrazuje. Rozhodne Nette\Database asi zavrhnu radeji na zacatku a zkusim dibi, ale byla by to skoda.
Jen podotykam, ze jediny zpusob jak jsem to dostal z databaze je prachsproste ciste SQL, k cemu nepotrebujeme cele Nette\Database :
Editoval OscarHanzely (19. 12. 2012 0:06)
- OscarHanzely
- Člen | 7
vvoody napsal(a):
Fungovať by malo:
Tak ako si to napísal, to s Discovered reflection ani nemôže fungovať.
Ten následný pokus s related ani netreba opravovať, buď nechápeš typ väzby medzi tvojimi tabuľkami, alebo ti nieje jasné, ktorú metódu použiť na akú väzbu.
To co si napisal, mi hadze chybu
Notice
Trying to get property of non-object
Znamena to, ze nevidi v tabulke data na previazanie ?
Data su nasledovne:
Vazby v tabulkach user<->user_rights_binding<->user_rights su 1:N:1
Nechapem asi spravne pouzitie metod ref a related. Ale preco v priklade s book-book_tag-tag pouzivaly $Book->tag->name co je podla dokumentacie related a moje $User->user_rights->description je rozdielne.
- OscarHanzely
- Člen | 7
Omlouvam se, ja uz zkousim uplne vsechno, tak jsem ho odebral. Samozrejme kdyz zmenim definici tabulky s dvojitym PK takto:
Tak se chyba nezmeni. :( Uz vazne nevim, co je na tom v zasade uplne spatne.
Dokonce uz jsem mel i pridany sloupec s nazvem id, ktery byl PK, protoze jsem si rikal, ze treba to ocekava na kazdou tabulku jeden hlavni jednosloupcovi PK a pak to hlasilo ty chyby nahore, ze nemuze vubec najit reference pres user_rights_binding. je to tak nestandartne navrzeno ? Dyt jsem okopiroval priklad z tutorialu s knihou, book_tag a tagem.
Editoval OscarHanzely (19. 12. 2012 18:48)
- OscarHanzely
- Člen | 7
Tak jsem na to konecne asi kapnul:
Vypis vsechna prava(jejich popisky) ktere jsou nabindovane k uzivateli oscar:
Ale musim rict, ze je to tezce neintuitivni co se kde vrati … pac related skoci jen o uroven vis, ale ref vytahne uz rovnou data. Nebo spise se musim zzit s tema castyma foreach, na ktere nejsem zvyklej pri dotazovani do db, ale az pri zpracovani dat.
Jo a stejne je tu jeden problem, bez tech parametru v related a ref, to nedokaze najit vubec zadny zavislosti, protoze bindovaci tabulka ma dvojity primary key. A to nedokaze pak ani ty FK na tabulku user_rights prechroupat :(
Jinak polozilo to nakonec 4 dotazy, misto jednoho JOINu pres dva tabulky. Je to vazne tak brutalne efektivni ?
Pro porovnani rucni dotaz:
Cas potrebyny pro ty 4 dotazy byl dle ladenky: 3.602ms
Cas pro vytazeni vseho v jednom dotazu s JOIN: 0.868ms
V cem je vlastne Nette\Database tedy lepsi ?
Editoval OscarHanzely (19. 12. 2012 20:12)