Nette DB – občasné vyhazování nedefinovaného sloupce
- Maxell92
- Člen | 38
Ahoj,
Máme na Nette rozjetých již několik projektů a čas od času mi
v e-mailu přistane velmi podivná chyba typu:
PHP Notice: Undefined index: 154 in Nette/Database/Table/Selection.php:862.
Výpis z Laděnky mi potom navíc řekne, že není definovaná proměnná
$item->name v šabloně (viz. níže).
Jedná se o velmi jednoduchý kód, klasická metoda default u presenteru v administraci, zjednodušeně:
$this->template->items = $this->model->findAll();
V šabloně potom pouze projdu výsledky cca takto:
{foreach $items as $item}
<a href="{link $defaultPresenter.':edit' $item->id}">{$item->name}</a>
{/foreach}
Chyba je naprosto náhodná. Projekt běží 2 měsíce, vše funguje a najednou se stane toto. Stránka hází chybu 500, smazání cache nepomůže. Děje se to jak na starší verzi Nette (cca 2.0.6), tak i na nejnovější 2.0.11.
Pomohlo mi v modelu ve funkci findAll přidat select:
return $this->getTable()->select('*');
Přijde mi to ale jako dost WTF řešení a osobně se mi nepodařilo zjistit proč se to děje a za jakých podmínek. Poradí někdo?
- Maxell92
- Člen | 38
Jasně, myslel jsem 2.0.12, sry :)
error.log: http://www.petrfidler.cz/…ka/error.log
Laděnka: http://www.petrfidler.cz/…3a0d773.html
- petr.pavel
- Člen | 535
Když tak koukám na ten error.log, tak to interpretuju takhle:
„Undefined index“ chceš záznam s hodnotou PK 154, ale ten neexistuje
„property of non-object“ nejspíš následek předchozího
„expects parameter 2 to be array“ rovněž
undeclared column „name“ mi ale přijde jako z jiné „rodiny“, protože z Laděnky vidím, že $item->id ti prošlo. Takže $item je objekt (ne null jako v případě předchozích chyb) a reprezentuje řádek výsledku dotazu do db, který má atribut id, ale nemá atribut name.
S prvním ti nepomůžu, druhé mi připomnělo chybu, se kterou jsem zápasil kdysi. NDB (nebo NotORM, už nevím) si pamatovalo, které sloupce jsem z výsledku dotazu použil, a tuhle informaci cacheovalo. Takže při příštím běhu místo SELECT * poslalo SELECT sloupec1, sloupec2. Jenomže když byl přihlášený jiný uživatel, tak se ještě předtím poslal trochu jiný dotaz do stejné tabulky, z jehož výsledku jsem použil jiné atributy. Cache je ale neobsahovala, takže SELECT taky ne. Řešením pro mě bylo přehodit cache ze souboru do session, aby měl každý uživatel svou.
- Caine
- Člen | 216
Nejjednodušší řešení je vypnout cachovaní (případně používat jen MemoryStorage), nebo explicitně uvádět výčet sloupců, který chceš vrátit. Nechápu, proč se od toho cachovaní použitejch sloupců úplně neopustí. Jsou s tím problémy několik let a stále se to nedaří pořádně opravit. Používám NDB na spoustě projektů (když se vypne cachovaní běhá to dobře) a než jsem vypnul cachovaní, vždycky tam byl nějakej problém s nedefinovaným sloupcem..
- Maxell92
- Člen | 38
Zkusil jsem to teď navodit a povedlo se mi to u jednoho projektu s určitou úspěšností, třeba po 5 pokusech se chyba objeví a dále to již nefunguje. Smazání cache nepomůže, opraví to jen uvedení select * (případně výčtu sloupců).
Když si udělám dump výsledku ve foreach, dostanu spoustu řádků, všechny s id 154. Řádek nemá žádná jiná data než ID. Záznam s tímhle id ale v databázi vůbec neexistuje, takže to zřejmě způsobí ty další chyby, které jsou již jen důsledkem.
- Caine
- Člen | 216
Maxell92 napsal(a):
Když si udělám dump výsledku ve foreach, dostanu spoustu řádků, všechny s id 154. Řádek nemá žádná jiná data než ID. Záznam s tímhle id ale v databázi vůbec neexistuje..
To trochu zavání výběrem sloupců z vícero tabulek, což pak u stejnejch sloupců vede k přepisování…
- Neo
- Člen | 5
Zdravím. Pořád je jediným navrhovaným řešením použít 2.1? Tahle chyba se nám začala projevovat na několika větších projektech a přejít na dev verzi nette globálně je nevyhovující, už jen proto, že bysme museli přepsat spoustu kódu kvůli SelectionFactory atd. Neopravil to už někde někdo, nebo nějaký workaround krom zakázání cache. nebo select *?