Matoucí zpráva: Argument passed to SmartCachingIterator::__construct must be…

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Grudl
Nette Core | 8227
+
0
-

Typická chyba v šabloně při použití makra {foreach ...} – člověk se překlepne a iteruje nad neexistující proměnnou nebo proměnnou s hodnotou NULL. Nette vyhodí výjimku:

Argument passed to SmartCachingIterator::__construct must be an array or interface Iterator provider, NULL given.

To je asi nejvíc matoucí výjimka celého frameworku ;) Vyhlašuju soutež na její přeformulování. Speciální bonus pro toho, kdo najde řešení zohledňující fakt, že SmartCachingIterator je třída existující nezávisle na LatteFilter a nějakých makrech.

Petr Motejlek
Člen | 293
+
0
-

Čím je tak strašně matoucí? Já vždycky tušil, co je špatně, když mi Laděnka hezky ukázala v tracu té výjimky, že za to může {foreach …}.

Lopata
Člen | 139
+
0
-

To je sice pravda, ale jak člověk čte rychle, toho překlepu si málokdy všimne. A ještě to umocňuje vlastnost lidskémo mozku podobné překlepy ignorovat. Takové chyby se pak hrozně těžce hledají a nejvíc naštvou. David má pravdu, že by ta vyjímka mohla být výřečnější…

Myslím, že asi nejlepší bude tam připsat doporučení, čím by to mohlo být způsobeno:

„Argument passed to SmartCachingIterator::__construct must be an array or interface Iterator provider, NULL given. It might be caused by a typo or unavailability of the desired variable in the template.“

To je, myslím, nejbezbolestnější…

Honza Kuchař
Člen | 1662
+
0
-

Řešení s doporučením se mi taky líbí.

pekelnik
Člen | 462
+
0
-

Daleko jasnější mi přijde:

<?php
'Invalid argument passed to foreach in template blemblem.phtml on line 80'
?>

Co myslíte?

Případnému doporučení ve formě požadovaného interfejsu se nebráním :)

Otázkou je zda se ve chvíli „spuštění“ šablony jsme schopni dostat k informacím o umístění v kódu zdrojové šablony… :|

Což mi připomíná jednu věc… zkusím ji sem napsat a uvidíme, ostatně to trochu souvisí…

Ve třídě LimitedScope na řádku 60 dochází pči chybě v šabloně k Parse Error ovšem člověk nemá šanci zjistit oč se jedná dokud před return v této funkci nepřidá

<?php
$code = func_get_arg(0);
file_put_contents(Environment::expand('%logsDir%/' . md5($code) . '-' . (string) microtime(TRUE) . '.php'), $code);
?>

Možná by stálo za to v takovém případě celý kus kódu zobrazit/uložit do logů. (V závislosti na módu)

Editoval pekelnik (12. 1. 2010 12:32)

Petr Motejlek
Člen | 293
+
0
-

Asi takhle: SmartCachingIterator by v žádném případě neměl tušit něco o tom, že byl volán z nějaké šablony. Měl by teda vyhodit vyjímku s textem, že obdržel null jako parametr. Potom by mělo něco, co renderuje tu šablonu, odchytit takovou výjímku, a přilepit k ní, že se jedná o chybu vyvolanou při renderování šablony na řádku tom a tom… Ergo nemám nic proti tomu, aby hláška vyjímky obsahovala řádek v šabloně, ale mám něco proti tomu, aby takovou vyjímku vyhazoval přímo už SmartCachingIterator ;).

pekelnik
Člen | 462
+
0
-

Souhlasím :)

Majkl578
Moderator | 1364
+
0
-

Taky.

David Grudl
Nette Core | 8227
+
0
-

Petr Motejlek napsal(a):

Potom by mělo něco, co renderuje tu šablonu, odchytit takovou výjímku, a přilepit k ní, že se jedná o chybu vyvolanou při renderování šablony na řádku tom a tom…

K tomu není potřeba ji odchytávat a modifikovat, informaci o jméně šablony (byť z cache) a číslu řádku obsahuje tak i tak.

Souhlasím, že SmartCachingIterator nemůže předpokládat použití v šabloně, nakonec proto jsem tohle téma otevíral, jinak by věc byla triviální. Takže chce to dostatečně šikovnou pragmatickou formulaci. Něco s dovětkem …probably you have passed NULL in foreach nebo tak.

David Grudl
Nette Core | 8227
+
0
-

Mimochodem, podobná věc je vypsání {$people}, kde $people je pole. Na to vyhodí htmlspecialchars:

Warning: htmlspecialchars() expects parameter 1 to be string, array given

které taky není úplně cool, nehledě na to, že SmartCachingIterator(NULL) končí výjimkou, kdežto tohle varováním. Chtělo by to sjednotit. Tady je věc jednodušší v tom, že bycha se objevuje v TemplateHelpers::escapeHtml(), kde už souvislost se šablonou lze předpokládat.

Jan Tvrdík
Nette guru | 2595
+
0
-

Co vytvořit potomka SmartCachingIterator speciálně pro foreach cyklus:

class TemplateForeachIterator extends SmartCachingIterator
{
	public function __construct($iterator)
	{
		try {
			parent::__construct($iterator);
		} catch (InvalidArgumentException $e) {
			throw new InvalidArgumentException('Invalid argument passed to foreach');
		}
	}
}
Petr Motejlek
Člen | 293
+
0
-

Pokud je SmartCachingIterator univerzalni (tj. nezavisi na sablone), je IMHO pragmaticke, aby o ni vubec netusil. Z tohohle duvodu se napr. vyjimky v Jave umi na sebe navazovat, aby bylo jasne, co zpusobilo co, a vubec jsme se o takove „hlouposti“ nemuseli bavit…

SmartCachingIterator by mel vyhodit nejakou vyjimku podobnou IllegalArgumentException(„Null passed to SmartCachingIterator.“), a tuhle vyjimku by si melo odchytit to, co renderuje tu sablonu. To by potom melo vytvorit neco jako TemplateProcessingException(„While processing the template file bleble.phtml on line X there was an exception thrown.“, IllegalArgumentException(„Null passed to SmartCachingIterator“).

Tohle se mi zda jako dostatecne primitivni, pragmaticka a funkci koncepce, ktera se muze pouzit naprosto kdekoliv.

PetrP
Člen | 587
+
0
-

Petr Motejlek napsal(a):

… Z tohohle duvodu se napr. vyjimky v Jave umi na sebe navazovat, aby bylo jasne, co zpusobilo co…

Od php 5.3 ma exception jako třetí parametr v constructoru $previos, tedy to co popisuješ.

Ondřej Mirtes
Člen | 1536
+
0
-

A Laděnka ukazuje Stack trace, tak to snad není potřeba :)

Petr Motejlek
Člen | 293
+
0
-

Ondřej Mirtes napsal(a):

A Laděnka ukazuje Stack trace, tak to snad není potřeba :)

A s tím taky souhlasím.

Jakub Lédl
Člen | 55
+
0
-

Já bych nechal původní chybovou hlášku, jelikož mi přijde naprosto v pohodě.

Je tam SmartCachingIterator (c'mon, každý, kdo dělá v Nette a někdy koukal do přeložených šablon VÍ, že {foreach} používá SmartCachingIterator), je tam popsán důvod chyby (očekávám pole|Iterator, šoupli mi NULL) a Nette\Debug ukáže, kde k chybě došlo.

NEBO: Foreach (a je jedno, jestli foreach (), nebo {foreach}, začátečníka to nezmate) has to iterate over an array or an Iterator interface implementation, but NULL was given.

Majkl578
Moderator | 1364
+
0
-

Jakub Lédl napsal(a):
začátečníka to nezmate

Otázkou je, jestli si tímto Nette guruové netvoří framework pro sebe? Pokud to začátečníka zmate, má důvod Nette odložit. A to nechceme, my chceme pravý opak, přilákat nové, ne?

Editoval Majkl578 (21. 1. 2010 17:17)

Jakub Lédl
Člen | 55
+
0
-

začátečníka to nezmate

bylo myšleno tak, že foreach může být chápáno jak jako foreach () {} pokud mám člověk PHP šablony, či jako {foreach}...{/foreach} pokud používá LatteFilters. Musí to pochopit i absolutní debil.

Honza Kuchař
Člen | 1662
+
0
-

Já bych to neměnil. Ale uznávám, že mě to jako začátečníka zmátlo. Udělal bych, jak tu bylo plánováno odkaz do wiki na webu nette.org, kde bych se dozvěděl více informací a třeba o tom, kdy ta chyba může nastat.

Vyki
Člen | 388
+
0
-

pekelnik napsal(a):

Daleko jasnější mi přijde:

<?php
'Invalid argument passed to foreach in template blemblem.phtml on line 80'
?>

Co myslíte?

Myslím, že něco jednoduchého v tomto smyslu by stačilo.

redhead
Člen | 1313
+
0
-

Jan Tvrdík napsal(a):

Co vytvořit potomka SmartCachingIterator speciálně pro foreach cyklus

Mě napadlo hned totéž. Myslím že to není špatné řešení. Je jen to pár řádků navíc..

Jakub Lédl
Člen | 55
+
0
-

Co toto znění:

Foreach statement cannot operate with variables of type ‚X‘ because ‚X‘ doesn't implement the Iterator interface.

Podle mě krátké, výstižné a společně s výstupem z Nette\Debug naprosto všeříkající (OK, není to tak úplně moje dílo, je to lehce upravená hláška, kterou vygeneruje C# kompilátor).

Uznávám, že tato hláška je možná příliš obecná, jelikož pokud standartnímu foreachi naservíruju objekt, tak si jeho členské proměné interně převede na pole a klidně iteruje přes ně (pro mě naprosto nepochopitelné chování). Ale řekl bych, že právě toto je jedna z věcí, které by se měl začátečník, pokud tuto prasárnu dělá, odnaučit! Vždyť je to naprosto exemplární bad-code smell.

Filip Procházka
Moderator | 4668
+
0
-

Jakub Lédl napsal(a):

Foreach has to iterate over an array or an Iterator interface implementation, but NULL was given.

+1

Petr Motejlek
Člen | 293
+
0
-

Jakub Lédl napsal(a):

Uznávám, že tato hláška je možná příliš obecná, jelikož pokud standartnímu foreachi naservíruju…

Já se už delší dobu domnívám, že naprostá většina automatických přetypování je špatná ;).

Ondřej Mirtes
Člen | 1536
+
0
-

A je to vyřešené :o)

https://github.com/…5e0d1b44ea2a

Petr Motejlek
Člen | 293
+
0
-

Ondřej Mirtes napsal(a):

A je to vyřešené :o)

https://github.com/…5e0d1b44ea2a

Já bych neřekl, že je to vyřešené ;). Spíš se to chová jako přilepit utrženou nohu izolepou k židli. Ale což, hlavně, že jste spokojení :D.