Vylepšená továrnička: create<componentName>($name)
- Jan Tvrdík
- Nette guru | 2595
Poznámka: je součástí frameworku od verze 0.9
Vytahuji vylepšenou továrničku, protože mi přijde škoda, že zapadla.
protected function createComponent($name)
{
if (String::lower($name) === 'component') {
return NULL;
}
$method = 'create' . $name;
if (method_exists($this, $method)) {
$component = call_user_func(array($this, $method));
if ($component instanceof IComponent && $component->getParent() === NULL) {
$this->addComponent($component, $name);
} elseif ($component->getParent() === NULL) {
is_callable(array($this, $method), TRUE, $textual);
throw new InvalidStateException("Function '$textual' must return instance of IComponent");
}
} else {
parent::createComponent($name);
}
}
Editoval Jan Tvrdík (3. 8. 2013 15:41)
- Honza Marek
- Člen | 1664
Taky by se teoreticky u komponenty s názvem component mohla zavolat metoda parent::createComponent. Otázka je, jestli to něco řeší, když tahleta továrnička stejně bude většinou v BasePresenteru.
- Honza Marek
- Člen | 1664
To je otázka, co třeba tam dát tuhletu skoro stejnou? :-D
/**
* Create component using create{Name} method
* @param string $name
*/
protected function createComponent($name) {
$method = "create" . $name;
if (method_exists($this, $method) && strtolower($name) !== "component") {
$component = call_user_func(array($this, $method), $name);
if ($component instanceof IComponent && $component->getParent() === NULL) {
$this->addComponent($component, $name);
}
} else {
parent::createComponent($name);
}
}
- romansklenar
- Člen | 655
Protože není problém udělat CTRL + C
a CTRL + V
do BasePresenteru
nebo BaseControlu
, když většinou
stejně nějaký základní presenter je? :)
Továrnička createComponent
je jen obecný mechanismus a
neurčuje konkrétní implementaci. Jestli si to člověk naimplementuje přes
switche, podmínky nebo přes toto je přece jen čistě na něm.
Začátečníky by mohlo volání callbacků dost zmást, proto si myslím že
je i dobře, že to není v distribuci.
- Honza Marek
- Člen | 1664
Stejně jako by je mohlo zmást volání action{Action} :)
Ale přišel jsem na jiné proti… Muselo by se každému vysvětlit, aby se
nepokoušel zavolat třeba $this->getComponent("template")
, což
pravda normálně nikoho ani nenapadne.
- jasir
- Člen | 746
romansklenar napsal(a):
Začátečníky by mohlo volání callbacků dost zmást, proto si myslím že je i dobře, že to není v distribuci.
Mě se zdá, že by to začátečníky určitě nemátlo, protože pak by „Návod na použití component v presenteru“ scvrkl na toto:
- Pro každou komponentu, kterou chceš použít v presenteru, vytvoř metodu createMyControl (nebo pro formuláře createMyForm), která vytvoří a vrátí nakonfigurovanou komponentu/formulář
- V template vykresli komponentu pomocí
{control MyForm}
nebo{wiget MyControl:specialRender}
- Pokud je zapotřebí dále manipulovat s komponentami například v
renderView()
, komponentu získáte pomocí$this->getControl('myForm')
Presenter se tedy za pomoci {widget}
a této továrničky
smrskne (v ideálním případě) do metod
createMyControl()
Honza M. napsal(a):
Ale přišel jsem na jiné proti… Muselo by se každému vysvětlit, aby se nepokoušel zavolat třeba$this->getComponent("template")
, což pravda normálně nikoho ani nenapadne.
Dobrá připomínka, jméno komponenty ‚template‘ by v ‚createMyControl()` mělo být asi zakázané stejně jako 'component‘.
Editoval jasir (6. 7. 2009 19:31)
- jasir
- Člen | 746
Honza M. napsal(a):
Asi nejvýstižnější by bylo
createComponent<Name>
, ale je to dost dlouhé.
Nebo zavést podtržítko…
<?php
protected function create_MyForm()
protected function create_MyWidget()
?>
- Pro: větší přehlednost, jasné odlišení widgetových továrniček, nikdy se nebude tlouct s Nette
- Proti: nehezké
Editoval jasir (7. 7. 2009 10:48)
- PetrP
- Člen | 587
jasir napsal(a):
Nebo zavést podtržítko…
To je proti Nette konvencím:
Functions and Methods
- camelCase
Honza M. napsal(a):
Asi nejvýstižnější by bylo
createComponent<Name>
, ale je to dost dlouhé.
To je popravdě nejvýstižnější, otázka je: je to create skutečně nutné?
- David Grudl
- Nette Core | 8227
Do frameworku je lepší nové věci přidávat teprve v okamžiku, když ostatním tak moc chybí, že vyhrožují fyzickým útokem nebo úplatkem :-)
Ale jo, přidat by se to mohlo. Na úrovni ComponentContainer
ne, na úrovni Control
by to mohlo být ideální. Nicméně název
by měl být dostatečně bezpečný a srozumitelný, což znamená
createComponent<Name>
.
- Honza Marek
- Člen | 1664
Hlásim nespokojenost s implementací chytřejší továrničky.
Potřeboval bych metodám createComponent<Name> předávat parametr $name, protože některé moje komponenty potřebují již v továrničce být připojené k presenteru.
Př.:
// v presenteru
protected function createComponentEditForm($name) {
new PageForm($this, $name);
}
// PageForm.php
class PageForm extends AppForm {
public function __construct($parent, $name) {
parent::__construct($parent, $name);
// definice
...
$this["id"]->setValue = $this->presenter->getParam("id");
}
}
Pokud by tenhle ne úplně šťastný příklad jako argument nestačil, zamyslím se a vymyslím lepší.
- romansklenar
- Člen | 655
Nepůjde to získat přes reflection z názvu metody? Ikdyž chápu, že je to zbytečně složité.
- PetrP
- Člen | 587
Jsem pro přidání, protože:
- při případném přejmenování ho změním na méně místech ;]
- méně psaní ;]
- můžu používat továrny na některé componenty (nebo jejich častí nastaveni, vytvoření)
- tahat si componenty z modelu (porad bojuju s myšlenkou ze tam např Form patří)
- dostane název case sensitive tak jak jsem si ho napsal v getComponent
- snadněji se mi migruje ze starého způsobu přes
createComponent($name) { switch ($name) ....
- něco si můžu například kešovat (nebo mít v sesions) v namespace podle nazvu componenty.
- parametr bude nepovinej, takže ho použiju jen když ho potřebuju.
Editoval PetrP (11. 7. 2009 22:58)
- Honza Marek
- Člen | 1664
romansklenar napsal(a):
Nepůjde to získat přes reflection z názvu metody? Ikdyž chápu, že je to zbytečně složité.
Tak jsou i jiný problémy. Pokud čachruju se šablonou, když ještě neni control připojený k presenteru, tak potom šablona nezná proměnnou $presenter (tudíž nefunguje ani plink a tak).