Nette\MemberAccessException po použití related

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

Zdravím lidičky,

mám problém s Nette\Database, konkrétně s použitím metody related.

Používám verzi Nette 2.0.10 stabilní, uvolněnou 6. 3. 2013 (tzn. v tuto chvíli aktuální stable verzi).
Tato věc se zde na fóru již řešila, nicméně např. zde bylo řešením přejití na novější verzi Nette, což u mě bohužel nejde (nicméně 2.1-dev jsem nezkoušel).

Chyba se vyskytuje víceméně náhodně, například po pokusu o vyhledání produktů v katalogu. Kód pro výcuc z databáze je následující:

<?php
public function getProduktMainObrazek($id)
{
    return $this->getProdukt($id)->related('produkt_obrazek')->where(array('typ' => 0))->fetch();
}
?>

Vrácený ActiveRow pak přidám k seznamu produktů takto:

<?php
foreach ($produktList as $prod)
{
    $prod['obrazek'] = $this->produktModel->getProduktMainObrazek($prod['id_produkt']);
}
?>

A už jen pošlu do šablony na vykreslení.

Databáze vypadá takto:
Tabulka produkt obsahující PK id_produkt.
Tabulka produkt_obrazek obsahující FK id_produkt.
Používám DiscoveredReflection.

Po jednom či více refreshi (F5) chyba zmizí a produkty se normálně načtou.

Očekávám, že je to chyba způsobená nějakým konfliktem pri cachování DB, nicméně vypnout cache samozřejmě není úplně košer řešení.

Budu rád za každou radu co s tím.
Díky :)

hrach
Člen | 1836
+
0
-

Cele to pouzivas spatne, ke kazdemu prvku z $produktList vybiras obrazek – tedy slozitost O(n). Pouzij nette database tak jak mas, tedy na itemu z $produktList volej related, a bude slozitost O(1). Vice se dozvis v me prezentaci a videu:

Izzy
Člen | 5
+
0
-

Díky za odpověď :)
Nevím jestli jsem se předtím vyjádřil dost srozumitelně. Jde mi o to, že data k produktu mám v tabulce produkt, a obrázky k tomu produktu mám v tabulce produkt_obrazek, kde se na produkt odkazuji pomocí FK id_produkt. K jednomu produktu existuje více obrázků, kde jeden (obrázek s vlastností typ = 0) je hlavní obrázek – a tento záznam odpovídající hlavnímu obrázku si já chci vytáhnout a přidat k výběru dat o produktu. Takže ve výsledku budu mít Selection obsahující několik produktů, každý produkt s vlastnostmi jako nazev, cena, barva a navíc ještě bude mít vlastnost obrazek, dodanou pomocí related. Svůj kód jsem trošku upravil tak, aby odpovídal tomu co je v prezentaci (mimochodem, prezentace nefunguje korektně v Chromu – po 5. slajdu se nepohne dál). Takže teď to vypadá následovně:

Výběr seznamu produktů z databáze (v modelu)

<?php
public function getProduktList($paginator = NULL)
{
    $produktList = $this->getTable()->order('id_produkt DESC');
    if(isset($paginator)) {
        $produktList->limit($paginator->getLength(), $paginator->getOffset());
    }
    return $produktList;
}
?>

Přiřazení obrázků (v presenteru)

<?php
foreach ($produktList as $produkt) {
    foreach ($produkt->related('produkt_obrazek') as $produkt_obrazek) {
        if($produkt_obrazek->typ == 0) {
            $produkt->obrazek = $produkt_obrazek;
        }
    }
}
?>

Předpokládám, že zde by to mělo jít řešit i pomocí $produkt->related('produkt_obrazek')->where(array('typ' => 0)), nicméně teď pro zkoušení to mám tak.

Možná Vám přijde divné, že tam ten obrázek přidávám tak divně, ale je to kvůli tomu, že nejprve vyberu jen ten seznam produktů s kterým pak manipuluji (nějaké where atd.) a až potom k těm produktům které v seznamu zbudou přidávám ty obrázky a pošlu seznam do šablony. (Kdybych tam obrázek připojoval rovnou v modelu tak mi ho z tama ty použití where zase vyhodí)

Takže tak jak to je teď by to mělo být správně? Chyba stále přetrvává.
Zjistil jsem, že ji „ručně“ vyvolám vždy když smažu cache, refreshnu stránku (načte se v pořádku), refreshnu znova a nastane MemberAccessException. Jinak se objevuje asi víceméně náhodně.

hrach
Člen | 1836
+
0
-

Spravne by sis nemel pouzivat „mezicache“

$produkt->obrazek = $produkt_obrazek;

ale related atp volat (asi) az v sablone.
Muzes to zkusit bez te mezicache?

A asi idealne muzes zkusit to na masterovi?