„Undefined offset“ při dotazu z databáze po vymazání cache

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

Ahoj,
podobný problém se tu už řešil, ale týkal se starších verzí Nette. Když použiju metodu count na výsledek získaný z databáze a poté na ten samý výsledek aplikuju metodu page, tak mi při vymazání cache Nette hodí výjimku Notice Undefined offset: .... Následné obnovení stránky už jede v pořádku.

Zkoušel jsem verze nette 2.0.5, 2.0.7, 2.0.8, 2.1dev, všechny se chovají stejně.

ProductModel.php:

public function getProducts()
{
    $products = $this->connection->table('product');
    return $products;
}

MainPresenter.php

public function renderProduct($page = 1, $category = null)
{
    $products = $this->productModel->getProducts();

    $paginatorComponent = $this->getComponent("paginator");
    $paginatorComponent->link = "Main:product";

    $paginator = $paginatorComponent->paginator;
    $paginator->page = $page;
    $paginator->itemsPerPage = 6;
    $paginator->itemCount = $products->count(); // KDYŽ ZAVOLÁM TOTO ZDE

    $this->template->products = $products->page($page, 6); // A PAK TOTO ZDE
}

Main.product.latte:

<div n:foreach="$products as $product">
	<div n:class="block, product, $iterator->odd ? odd : even">
        <h2>{$product->name}</h2> {* TAK TO ZDE VYHODÍ VÝJIMKU *}
        ...
   </div>
</div>

Uiii

Editoval uiii (29. 1. 2013 14:04)

hAssassin
Člen | 293
+
0
-

co je metoda page() nad selection? Neni tam jen limit() pro orez vysledku na dany pocet?

EDIT: sorry za OT, zda se ze tam jsou obe metody :)
EDIT2: abych ale nebyl uplne OT, nemas $page nahodou zapornou?

Editoval hAssassin (29. 1. 2013 14:25)

Richard Jedlička
Člen | 51
+
0
-

No ta dělá stránkování. Aspoň to tak chápu a funguje mi to tak.

castamir
Člen | 629
+
0
-

count("*") funguje?

Edit: Nastavujes si $paginator, ale pro orez dotazu ho, zda se, nepouzivas. Bez ohledu na to, ze z uvedeneho kodu nevime, zda $paginator nepouzivas i jinde, nebo co je obsahem te metody page nad $product

Editoval castamir (29. 1. 2013 14:34)

Richard Jedlička
Člen | 51
+
0
-

hAssassin napsal(a):
abych ale nebyl uplne OT, nemas $page nahodou zapornou?

Ne, to ne. Jak říkám hází to jen hned po vyčištění cache. Po aktualizaci stránky (úplně stejná url) to funguje v pohodě.

castamir
Člen | 629
+
0
-

Jinak ta chyba ve starsich verzich se projevovala presne naopak. Stranka se zobrazila (platilo jen pro dev) jen po zmazani cache

Richard Jedlička
Člen | 51
+
0
-

castamir napsal(a):

count("*") funguje?

Ty jo, s tou hvězdičkou to funguje. Jsem očekával, že prostě count metoda vrátí počet prvků jako u pole (zkoušel jsem i count($products) ale chovalo se to stejně).

Editoval uiii (29. 1. 2013 14:38)

ViPEr*CZ*
Člen | 811
+
0
-

Todle $products->count(); nad celou Selection je blbost. To jestli se nepletu zavolá
count(„pole ze selekšny“); a to vlastně vrátí všechny řádky. Zavolal bych $products->count(„“); což vyvolá dotaz do SQL COUNT().
Metoda page volá toto:

return $this->limit($itemsPerPage, ($page - 1) * $itemsPerPage);

Takže to je jen alias k metodě limit. Což by ale padat nemělo v kombinaci s count(„*“) a měli by se volat dva SQL dotazy.

Richard Jedlička
Člen | 51
+
0
-

castamir napsal(a):

Edit: Nastavujes si $paginator, ale pro orez dotazu ho, zda se, nepouzivas. Bez ohledu na to, ze z uvedeneho kodu nevime, zda $paginator nepouzivas i jinde, nebo co je obsahem te metody page nad $product

Ta metoda page je metoda z Nette na třídě Selection https://api.nette.org/…ion.php.html#368.

EDIT: píše o tom ViPEr*CZ* https://forum.nette.org/…mazani-cache#…

Editoval uiii (29. 1. 2013 14:46)

Richard Jedlička
Člen | 51
+
0
-

Je teda ale divný, že použití metody count bez parametrů nefunguje (teda funguje ale ne ve spojení s následným stránkováním). Podle API dokumentace to má bez parametrů dělat co bych očekával.

EDIT: problém teda asi bude volání page (nebo nejspíš jakéhokoli dotazu) na Selection, která byla vyhodnocena (execute).

Editoval uiii (29. 1. 2013 14:53)

castamir
Člen | 629
+
0
-

A safra. Toho jsem si nikdy nevsiml :D. Clovek se porad uci :-)

hrach
Člen | 1834
+
0
-

Je to naprosto zrejme:

  • metoda count s parametrem spousti oddeleny dotaz do db, kde se provede SELECT COUNT(*), takto by to melo byt naprogramovane
  • bez parametru to fetchne vsechna data a spocita pocet radku
  • nicmene to, ze potom nefunguje page() je chyba, kterou se pokusim opravit.
hrach
Člen | 1834
+
0
-

Potrebuji videt landeku a obsah getProducts().

Richard Jedlička
Člen | 51
+
0
-

hrach napsal(a):

Potrebuji videt landeku a obsah getProducts().

Rád zašlu jen mi pověz, jak to nejlépe udělat. Když uložim laděnku jako stránku, tak to stejně potřebuje běžící web pro zobrazení obsahu souboru a tak. A co se týče getProducts(), tak ti stačí dump?

hrach
Člen | 1834
+
0
-
  • getProducts: ne, spis potrebuju definici, co tam uvnistr provadis.
  • ladenka: nejlepsi by bylo vynout produkcni mod a poslat soubor vygenerovany do logu.
enumag
Člen | 2118
+
0
-

@hrach: Zřejmě jsi myslel zapnout produkční mód. Nevadí ti, že v produkčním módu se ignoruje notice a výsledná chyba tedy bude jiná?

Richard Jedlička
Člen | 51
+
0
-

enumag napsal(a):

@hrach: Zřejmě jsi myslel zapnout produkční mód. Nevadí ti, že v produkčním módu se ignoruje notice a výsledná chyba tedy bude jiná?

JJ, zapnul jsem si produkční mód a výsledná chyba opravdu jiná je, ale třeba se z ní taky něco zjistí.

Richard Jedlička
Člen | 51
+
0
-

Obsah getProducts máš v prvním příspěvku. Ve skutečnosti tam toho dělám víc, ale zkoušel jsem to v téhle nejjednodušší formě a taky nefungovalo.

EDIT: Jestli to nejde stáhnout tak tady je odkaz do dropboxu: https://www.dropbox.com/…7/HeXvaVfcAH

Editoval uiii (29. 1. 2013 18:06)

Jirda
Člen | 103
+
0
-

Jen se pridam, ze jsem si pri vyvoji na jednom projektu vsiml podobneho problemu.

Nette Framework 2.1-dev (revision $WCREV$ released on $WCDATE$)
Hmm, koukam ze ladenka nevypsala $WCREV$ a $WCDATE$ – prepokladam, ze by tam za to mely byt dosazeny hodnoty. ALe to je jiny pribeh.

hrach
Člen | 1834
+
0
-

Ad notice v produkcnim: tomu by mel pomoci $strictMode. Ohledne tech dvou souboru, mozna jsem natvrdlej, ale neprisel jsem na to, jak je stahnout. Akorad mi to udela progressbar predemnou…

Richard Jedlička
Člen | 51
+
0
-

No co se týče $strictModu, tak ten mám v config.neon nastaven na true, ale stejně to nezachytí. Proč ti to nenabídne dialog na uložení to nevim, dal jsem tam ještě odkaz na dropbox.

hrach
Člen | 1834
+
0
-

Ahoj, strict mode generuje jen info, ale ne ladenku… blbnu no… diky za dropbox :)

hrach
Člen | 1834
+
0
-

No nic, asi potrebuju tu notice… :| a taky obsah te metody!

Richard Jedlička
Člen | 51
+
0
-

hrach napsal(a):

No nic, asi potrebuju tu notice… :| a taky obsah te metody!

Tak tady je ta notice: https://www.dropbox.com/…da917cc.html . Dalo to celkem zabrat :-) Nejdřív jsem musel najít ve zdrojácích, kde se loguje na produkčnim serveru a pak si to ručně zapnul i development mode. Je možný, že střílim vrabčáky kanónem, ale jednodušší způsob mě nenapad.

No a obsah tý medoty:

public function getProducts(
    $filterParams = array(
        'category' => null,
        'tags' => array(),
        'minPrice' => null,
        'maxPrice' => null
    )
)
{
    $products = $this->connection->table('product');

    if($filterParams['category'])
    {
        $products = $products->where("product_category:category.url_name", $filterParams['category']);
    }

    if($filterParams['tags'])
    {
        $products = $products->where("product_tag:tag.name", $filterParams['tags']);
    }

    if($filterParams['minPrice'])
    {
        $products->where('price >= ?', $filterParams['minPrice']);
    }

    if($filterParams['maxPrice'])
    {
        $products->where('price <= ?', $filterParams['maxPrice']);
    }

    return $products;
}

Ale jak jsem řikal. V situaci, kdy nastává ta Notica, se nepoužije ani jedna filtrační podmínka.