Presenter::extensionMethod se nepromítá do tryCall
- Mikulas Dite
- Člen | 756
Presenter::tryCall()
volá jenom
Presenter::getReflection()->hasMethod()
. To je originální
funkce z \ReflectionClass
a předpokládám, že volá upravenou
getMethods()
. Nejsou v ní ale rozšíření z
extensionMethod()
.
class CustomPresenter extends Presenter {}
$p = new CustomPresenter();
$p->extensionMethod('actionDynamic', callback(...));
// životní cyklus presenteru se poté při requestu `Custom:dynamic` dostane k:
$p->tryCall('actionDynamic', array());
// a na tom selže
První možnost je přidat do tryCall() ještě jednu podmínku, něco jako tohle.
Druhá možnost je upravit getMethods()
(a tedy
hasMethod
?) tak, aby brala na vědomí i rozšíření. To by ale
znamenalo, že Callback by musel získat další metodu
getTargetReflection
, což by byla
MethodReflection/FunctionReflection toho callbacku (callback->reflection je
teď jenom reflexe třídy callback).
Tohle využijí například komponenty, které potřebují nějakou akci (třeba kvůli ajaxu).
- David Grudl
- Nette Core | 8218
Upravit třídy reflexe nejde, hasMethod by ošálit šlo, ale getMethod ne, nelze vytvořit ReflectionMethod pro virtuální metodu. Podpora by tedy musela být cíleně v tryCall, jenže nemyslím, že by to byl krok správným směrem, s extension method je třeba zacházet opatrně.
- Filip Procházka
- Moderator | 4668
Osobně si nemyslím, že to je potřeba, bylo by to až moc magické. A určitě to, co chceš implementovat půjde i bez toho :)
- Martin
- Člen | 171
Zdravím. Nevím, jak jste to nakonec vyřešili, já mám pro provizorní rozchození právě dodělávané komponenty něco takového (samozřejmě ve výsledku to bude jinak):
protected function tryCall($method, array $params)
{
$rc = $this->getReflection();
if ($rc->hasMethod($method)) {
$rm = $rc->getMethod($method);
if ($rm->isPublic() && !$rm->isAbstract() && !$rm->isStatic()) {
$rm->invokeNamedArgs($this, $params);
return TRUE;
}
}
else if ($rc->getExtensionMethod($method)) {
Nette\ObjectMixin::call($this, $method, $params);
return TRUE;
}
return FALSE;
}
Byla by to příliš velká bezpečnostní díra, nebo proč to není vhodné používat? Mně by se to docela hodilo kvůli jednoduchému svázání handleru komponenty s callbacky v presenteru, ale už to holt začínám dotvářet jinak.
Editoval Martin (8. 4. 2011 1:40)
- Martin
- Člen | 171
Tak jsem to nakonec dovedl k funkčnosti bez přepisování TryCall. Ale je to takto správně (ve třídě poděděné od AppControl, aby fungoval parametr ?do=jmenoKomponenty-jmenoHandleru)?
public function signalReceived($signal)
{
if ($signal === 'submit') {
return parent::signalReceived($signal);
} else {
$method = $signal == NULL ? NULL : 'handle' . $signal;
$rc = $this->getReflection();
if ($rc->hasMethod($method)) {
$rm = $rc->getMethod($method);
if ($rm->isPublic() && !$rm->isAbstract() && !$rm->isStatic()) {
$presenter = $this->getPresenter();
$params = $presenter->getParam();
$rm->invokeNamedArgs($this, $params);
return TRUE;
}
}
}
throw new BadSignalException("There is no handler for signal '$signal' in class {$this->reflection->name}.");
}
Přijde mi to trochu jako drbání se pravou rukou za levým uchem. Proč se vlastně komponentě nepředávají parametry? U presenteru to nevadí, sám sobě si je dávat nemusí. Nebo se prostě s touto cestou vytváření aktivní komponenty v Nette záměrně nepočítá?
Editoval Martin (8. 4. 2011 3:23)
- David Grudl
- Nette Core | 8218
Proč se vlastně komponentě nepředávají parametry
Komponentně se parametry předávají. Selže to tehdy, pokud si přepíšeš kontruktor a nezavoláš parent::__construct()