{widget test} ← mel by umirat na neimplementovanem rozhrani ITemplate
- vkuzel
- Člen | 15
Ahoj,
používám NetteFramework-0.9.3-PHP5.2, ve kterém jsem si vytvořil šablonu volající komponentu test, následujícím způsobem:
{widget test}
Framework mi v presenteru zavolá metodu createComponentTest()
ze které vrátím vytvořenou třídu/komponentu Test, následovně:
<?php
protected function createComponentTest() {
return new Test();
}
?>
Pokud třída Test
neimplementuje rozhraní
IComponent
, framework vyhodí výjimku Component with name
‚test‘ does not exist. a to díky kusu kódu v souboru
Nette/ComponentContainer.php
na řádku 144 který ověří,
zda-li komponenta implementuje rozhraní IComponent
a pokud ne, tak
ho nevloží do pole komponent:
<?php
if (!isset($this->components[$name])) {
$component = $this->createComponent($name);
if ($component instanceof IComponent && $component->getParent() === NULL) {
$this->addComponent($component, $name);
}
}
?>
Potud je vše v pořádku. Problém nastává v následujícím případě.
Šablonovací systém přeloží příkaz {widget test}
na
<?php $control->getWidget("test")->render() ?>
,
přičemž rozhraní IComponent neobsahuje metodu render()
, takže
jakmile se skript dostane na volání této metody v šabloně skončí fatal
errorem, přitom bych očekával vyhození výjimky, obdobně jako
v předchozím případě.
Pokud metoda ComponentContainer::getComponent()
vždy vrací
komponentu, u které bude volána metoda render()
, žřejně bych
rozšířil řádek 144 o kontrolu rozhraní ITemplate
, které
inkriminovanou metodu obsahuje. Pokud ne, kontrola by měla být zřejmě někde
jinde (v metodě getWidget()
?).
Rozšířená kontrola:
<?php
if (!isset($this->components[$name])) {
$component = $this->createComponent($name);
if ($component instanceof IComponent && $component instanceof ITemplate && $component->getParent() === NULL) {
$this->addComponent($component, $name);
}
}
?>
S frameworkem se teprve seznamuji, takže nechám rozřešení na laskavém čtenáři.
p.s. teď koukám, že přidání této podmínky by si vynutilo i úpravy
jinde ve frameworku, například přidání ITemplate
ve tříde
/Nette/Forms/Form
, která sice obsahuje metodu
render()
, ale v definici neimplementuje rozhraní
ITemplate
ani ždáný z jejích předků.
- Ondřej Mirtes
- Člen | 1536
Kdysi mě napadlo, že by měla být někde vynucena metoda render(), např. pomocí rozhraní IControl (ITemplate s tím má málo společného), ale tu by nesplňoval ani Presenter.
Vem si, že můžeš po potomku třídy Control (na kterém to makro widget voláš) chtít existenci nějaké jiné metody, než té s názvem render. Widget makro umožňuje třeba i tento zápis:
{widget komponenta:test}
čímž se zavolá metoda renderTest()
. Anebo můžeš pomocí
widget makra předávat parametry:
{widget komponenta test}
čímž se zavolá metoda render('test')
, takže by PHP
zařvalo, že hlavička metoda není kompatibilní s tou v interface.
- vkuzel
- Člen | 15
Ahoj, díky za info. Rozšířené volání widgetu jsem si neuvědomil.
Přesto by se možná framework mohl vyjádřit trochu jasněji, co se týče
chyby. Pokud neimplementuju rozhraní IComponent
, tak nedostanu
hlášku, že komponenta není správná, že nemá správné rozhraní, ale
napíše mi to, že neexistuje. A když neimplementuju metodu
render()
, tak to skončí fatalem na neexistující metodě.
Líbily by se mi hlášky jako, „Komponenta xxx musí implementovat
rozhraní IComponent“, případně „Komponenta xxx musí mít metodu
render()/renderCokoli()“ (dalo by se kontrolovat třeba pomocí funkce
method_exists()
), člověk pak bude hned vědět kde je problém.
V současném stavu musím i v kódu frameworku hledat, kde je chyba, ale je
to jenom maličkost.