registerHelperLoader() se dožaduje onPrepareFilters()
- Dragon Jake
- Člen | 20
Zdravím,
nejsem si jistý, jestli jde o bug nebo o undocumented feature,
každopádně by bylo vhodné na to alespoň upozornit. V presenteru volám
$template->registerHelperLoader('KAdm\CustomHelpers::register')
na zaregistrování helperů, které fungují v pořádku. Avšak pokud třídu
KAdm\CustomHelpers
extenduji od Nette\Object
, dočkám
se tohoto:
Call to undefined static method KAdm\CustomHelpers::onpreparefilters().
Inu dobrá, definuji statickou metodu onPrepareFilters()
a
prázdnou, jelikož mě nenapadá, co jiného by tam mělo být. Excepšna
zmizí, aplikace doběhne, ale bez Latte filteru (který jinak startuje
automaticky). Co s tím? Prozatím tiše ignoruji volání neexistující
statické metody prostým zakomentováním dědění od
Nette\Object
.
Používám jednu z posledních revizí Nette 1.0-dev na PHP 5.3.
- David Grudl
- Nette Core | 8228
$onPrepareFilters je proměnná definovaná v šabloně. Je to pole
callbacků, které se zavolají přes
$template->onPrepareFilters()
. Jakým způsobem ti to koliduje
netuším…
- Jan Tvrdík
- Nette guru | 2595
Při pohledu do zdrojových kódů jsem došel k názoru, že máte blbě napsaný HelperLoader. Příklad jednoduché implementace se nachází i v dokumentaci.
- leumas
- Člen | 13
HelperLoader mam napisany presne podla prikladu v dokumentacii s jedinym rozdielom: dedim od Objectu (propaganda \Nette\Objectu ako prapredka vsetkeho na mna zjavne zabrala;-)) A to je zdroj problemov. Funkcia isCallable je naimplementovana ako phpckovske is_callable, ktore vracia vzdy true v pripade, ze trieda obsahuje __call metodu. Kedze je vsak trieda zdedena od Objectu, magic __call obsahuje a Helper sa preto tvari, ze danu metodu obsahuje a vrati jej callback.
Ono, chcelo by to asi, aby phpcko malo nejaku magic metodu __isCallable. Do dokumentacie by som navrhoval pridat k prikladu varovanie ludi pred implementovanim __call metody, ci dedenim z Objectu.
- leumas
- Člen | 13
Mimochodom, preco helperLoader dostava lowercase nazov metody, ktoru treba zavolat? Je to pomerne neprijemne, ak pouzivam helpery s camelcase.
Sorry, moja chyba, funkcie v php su narozdiel od premennych case insensitive, takze to neprekaza. Ten jazyk ma stale prekvapuje…
Editoval leumas (3. 9. 2010 14:30)
- leumas
- Člen | 13
arron napsal(a):
Myslim, ze jsem podobny problem resil nedavno. Jestli si dobre pamatuju, tak to bylo tim, ze trida s helpery mi delila od Object. Pak jsem dostaval presne tuhle chybu. Odstranenim dedeni se problem vyresil.
No ano, ako vravim, je to sposobene tym, ze Object implementuje magic __call a tym padom funkcia is_callable vyhodnoti vsetky callbacky na danej triede ako callable, tj. vzdy vrati true.
- Jan Tvrdík
- Nette guru | 2595
Pokud je definované metoda __call
tak nesmíte použít funkci
is_callable
, ale nahraďte ji funkcí
method_exists
.
- arron
- Člen | 464
leumas napsal(a):
No ano, ako vravim, je to sposobene tym, ze Object implementuje magic __call a tym padom funkcia is_callable vyhodnoti vsetky callbacky na danej triede ako callable, tj. vzdy vrati true.
Ech, malo ctu a brzo pisu. Pardon;-) Nicmene zrovna v pripade toho helperu je IMHO naprosto zbytecne dedit od Object (tez jsem podlehnul, nicmene se ukazuje, ze vsechno je potreba delat s rozvahou;-))
- Bernard Williams
- Člen | 207
Nazdárek,
neporadil by mi někdo nějaký rychlý fix, aby mi Nette pro verzi PHP 5.2 jelo na verzi PHP 5.3? Teď mi Nette háže chybu: Call to undefined static method Helpers::onpreparefilters()
Call stack:
- 1. inner-code Object:: __callStatic
- 2. inner-code Helpers:: onpreparefilters
- 3. Utils/Callback.php (112) source ▼ call_user_func_array
Line 107: public function invokeArgs(array $args)
Line 108: {
Line 109: if (!is_callable($this->cb)) {
Line 110: throw new InvalidStateException("Callback '$this' is not callable.");
Line 111: }
Line 112: return call_user_func_array($this->cb, $args);
Line 113: }
Budu rád za každou radu.
Bernard
- Ondřej Mirtes
- Člen | 1536
Ahoj,
Nette pro PHP 5.2 je s PHP 5.3 plně kompatibilní, chyba bude na tvé
straně. V Nette žádná třída Helpers není, předpokládám, že tuto
chybu vyvolává tvůj kód. Ukaž nám celou stack trace a především
poslední místo v ní, kde se ještě jedná o tvůj kód (před cestou do
Nette).
- Bernard Williams
- Člen | 207
Díky z reakci. Obávám se, že chyba je opravdu na straně Nette. Pokud existuje cache, tak se webová stránka zobrazí. Pokud jej ale smažu, tak to hodí chybu.
Jo a když se pokusím zobrazit jinou stránku než index, tak to hodí chybu 404, což na PHP 5.2.5 taky nedělá.
- bojovyletoun
- Člen | 667
- dumpnul bych $this->helpers.
- pak bych sledoval this->cb.
- je správně onPrepareFilters s velikostí písmen? Dle mě se tady už jeden bug(php dokonce 5.2) řešil v souvislosti s PDO a Nette\Database a onquery zde
- což potvrzuje původní podzření, že php 5.2 je na objekty málo vyzrálé
PS: kdo bude uvádět při sčítání lidu víru
Nette framework
?
Editoval bojovyletoun (2. 3. 2011 23:42)
- Bernard Williams
- Člen | 207
V souboru Utils/Callback.php na řádku return call_user_func_array($this->cb, $args); proměnná this->cb obsahuje:
array(2) [
0 => "Helpers" (7)
1 => "onpreparefilters" (16)
]
V souboru Templates/Template.php na řádku return $this->helpers[$lname]->invokeArgs($args); proměnná $this->helpers obsahuje:
array(10) {
"escape" => Callback(1) {
"cb" private => "TemplateHelpers::escapeHtml" (27)
}
"escapeurl" => Callback(1) {
"cb" private => "rawurlencode" (12)
}
"striptags" => Callback(1) {
"cb" private => "strip_tags" (10)
}
"nl2br" => Callback(1) {
"cb" private => "nl2br" (5)
}
"substr" => Callback(1) {
"cb" private => "iconv_substr" (12)
}
"repeat" => Callback(1) {
"cb" private => "str_repeat" (10)
}
"replacere" => Callback(1) {
"cb" private => "String::replace" (15)
}
"implode" => Callback(1) {
"cb" private => "implode" (7)
}
"number" => Callback(1) {
"cb" private => "number_format" (13)
}
"onpreparefilters" => Callback(1) {
"cb" private => array(2) [
0 => "Helpers" (7)
1 => "onpreparefilters" (16)
]
}
}
$lname obashuje:
"onpreparefilters" (16)
$args obsahuje:
array(1) [
0 => FileTemplate(7) {
"file" private => "C:\WWW\www.maturitni-tabla.cz\Web/app/FrontModule/templates/Homepage/default.phtml" (82)
"warnOnUndefined" => TRUE
"onPrepareFilters" => array(1) [
0 => Callback(1) { ... }
]
"params" private => array(11) {
"control" => Front_HomepagePresenter(33) { ... }
"presenter" => Front_HomepagePresenter(33) { ... }
"user" => User(8) { ... }
"baseUri" => "/www.maturitni-tabla.cz/Web/" (28)
"basePath" => "http://localhost/www.maturitni-tabla.cz/Web" (43)
"flashes" => array(0)
"login_form" => AppForm(17) { ... }
"tabla" => DibiResult(6) { ... }
"layout" => "C:\WWW\www.maturitni-tabla.cz\Web/app/templates/@layout.phtml" (61)
"_extends" => "C:\WWW\www.maturitni-tabla.cz\Web/app/templates/@layout.phtml" (61)
"template" => FileTemplate(7) { *RECURSION* }
}
"filters" private => array(0)
"helpers" private => array(10) {
"escape" => Callback(1) { ... }
"escapeurl" => Callback(1) { ... }
"striptags" => Callback(1) { ... }
"nl2br" => Callback(1) { ... }
"substr" => Callback(1) { ... }
"repeat" => Callback(1) { ... }
"replacere" => Callback(1) { ... }
"implode" => Callback(1) { ... }
"number" => Callback(1) { ... }
"onpreparefilters" => Callback(1) { ... }
}
"helperLoaders" private => array(2) [
0 => Callback(1) { ... }
1 => Callback(1) { ... }
]
}
Nějak vůbec nevím co s tím :-/
]
- Ondřej Mirtes
- Člen | 1536
Nekde ve svem kodu si registrujes callback Helpers::onPrepareFilters(), ktery ovsem neexistuje.
- Bernard Williams
- Člen | 207
To já nedělám, to dělá Nette – celý Call stack je z Nette.. A i kdybych Helpers::onPrepareFilters() definoval sám, nemyslíš, že by to pak nejelo ani na PHP 5.2? Nejspíš ne, že? Ale ono jede.. takže chyba bude někde ve způsobu volání.. se kterým si PHP 5.3 neumí poradit.. a já bohužel nemůžu přijít na to kde a už vůbec ne na to, jak to opravit :-/
- Jan Tvrdík
- Nette guru | 2595
Začni tím, že si projdeš všechny výskyty řetězce
onPrepareFilters
v celém projektu.
- Ondřej Mirtes
- Člen | 1536
Když v aktuálním Nette sandboxu vydumpuju
$template->getHelpers()
, je jich tam jen devět. Ten desátý si
opravdu registruješ sám a pravděpodobně nějakým způsobem, který na PHP
5.2 funguje, ale na 5.3 ne.
Zkus na svůj projekt pustit fulltextové hledání „registerHelperLoader“ a „registerHelper“ a uvidíš.
- Bernard Williams
- Člen | 207
Chlapi, smekám.
onPrepareFilters bylo jen v Nette, ale při zakomentování registerHelperLoader to fungovalo. Při bližším zkoumání byl problém ve scriptu Helpers s definicí jednotlivých helprů. Konkrétně bylo potřeba místo:
$callback = callback(__CLASS__, $helper);
if ($callback->isCallable()) {
return $callback;
}
dát:
if (is_callable($callback = __CLASS__ . '::' . $helper))
return $callback;
což funguje jak na PHP 5.3, tak i na PHP 5.2.
Mockrát všem děkuji!
- Milo
- Nette Core | 1283
Právě jsem se setkal s tou samou chybou u aktuální verze Nette
z Githubu. Migroval jsem aplikaci z 5.2 na 5.3. Jak je výše uvedeno, chyba
vznikne při dědění z Nette\Object
.
// Starý helper loader
class Helpers extends Nette\Object
{
public static function loader($helper)
{
if (is_callable(__CLASS__ . '::' . $helper)) // vždy TRUE, protože Object implementuje __callStatic()
{
return callback(__CLASS__, $helper);
}
return NULL;
}
}
// Funkční nová verze
class Helpers extends Nette\Object
{
public static function loader($helper)
{
if (method_exists(__CLASS__, $helper))
{
return callback(__CLASS__, $helper);
}
return NULL;
}
}
Zvláštní (side effect?) je, že metoda Helpers::loader()
je
volána s parametrem onpreparefilters
. Někde se tedy zavolá
Helpers::loader('onpreparefilters')
a to asi tady
a to pouze při kompilaci šablony. Má to nějaký důvod?