Best Practice: Mají mít komponenty parenta? Být připojeny k presenteru?
- Achse
- Člen | 44
Z diskuze zde mi vyplynula jedna otázka: https://forum.nette.org/…at-formulare
Všiml jsem si (tu na foru, v docách), že strašmě mockrát se dělají komponenty bez parenta. Je to správně? Důsledkem totiž je, že komponenta není připojena k presenteru a to přináší různé problémy.
Mám zvyk, že všechny presentery v aplikaci dědí o jednoho
BasePresenteru, všechny komponenty od BaseControlu a všechny formuláře
dědí nebo jsou přímo instancí nějuakého mého App\Formu
.
Navíc důsledně všechny komponenty a formuláře připojují
k presenteru.
Je to správně? Proč případně nění a jaký je best practise?
Zde je ukázka kódu jak ± vypadá můj BaseControl.
abstract class BaseControl extends Control {
/** @var Translator */
public $translator;
public function __construct(IContainer $parent = NULL, $name = NULL) {
if (!$parent) {
throw new \Exception("Component must have \$parent.", NULL);
}
if (!$parent instanceof \App\Controls\BaseControl AND !$parent instanceof BasePresenter) {
throw new \Exception("\$parent must be instance of \App\Controls\BaseControl or \BasePresenter.");
}
$this->translator = $parent->translator;
parent::__construct($parent, $name);
}
public function setLocalTemplateFile($name) {
$this->template->setFile(dirname($this->reflection->getFileName()) . '/' . $name);
}
protected function registerHelper($helper, $template) {
if (method_exists ($helper , 'injectTranslator')) {
$helper->injectTranslator($this->translator);
}
$template->getLatte()->addFilter(NULL, array($helper, 'loader'));
}
public function createTemplate($class = NULL) {
$template = parent::createTemplate($class);
$template->setTranslator($this->translator);
// HELPERS
$this->registerHelper(new Helpers(), $template);
$this->registerHelper(new \App\Helpers\Helpers(), $template);
return $template;
}
/**
* @param bool $need
* @return \BasePresenter
*/
public function getPresenter($need = TRUE) {
return parent::getPresenter($need);
}
/**
* NOTE: render() can't be declared here, breakes child controls with render with arguments
*/
}
Editoval Achse (16. 6. 2014 13:26)
- mkoubik
- Člen | 728
Komponentu můžeš připojit k předkovi dvěma způsoby:
- Přímo:
$parent->addComponent($component, 'nazev')
nebo$parent['nazev'] = $component
. Tohle dělá automaticky metodagetComponent()
, takže pokud použiješ továrničkucreateComponentNazev()
tak už nic předávat nemusíš. To je doporučený způsob. - V konstruktoru (to je to co děláš ty). Tenhle způsob je v nette hlavně kvůli zpětné kompatibilitě se starým kódem.
Výhoda první varianty je, že máš volný konstruktor. Komponenta je ale
funkční (připojená) až v meodě attached()
, takže bys s ní
v konstruktoru neměl dělat nic složitějšího, než nastavení
závislostí.
- MartinitCZ
- Člen | 580
Jak do komponent předáváš závislosti? Tímto řešením
__constructor-u si to jen stížíš.
Osobně taky používám nějaký BaseControl, BasePresenter, BaseForm např.
k nastavení vzhledu, jazyka translátoru …, ale __constructor
používám jedině k předání vlastních závislostí.
Tzv. žádný __construct(IContainer $parent = NULL, $name = NULL)
mě nezajímá (+ si myslím, že je to dokonce deprecated). Funguje to i bez
nich :)
Snad ti to nějak pomůže.
Editoval martinit (16. 6. 2014 13:05)
- mystik
- Člen | 308
Já taky :-) Proto to mám vyřešeno takhle:
<?php
protected function attached($component) {
parent::attached($component);
if($component instanceof TranslatorAware) {
$this->setTranslator($component->getTranslator());
}
}
?>
TranslatorAware je rozhraní definující jenom getTranslator() a mají ho všechny moje komponenty a presentery.
- Quinix
- Člen | 108
Lepší je konstruktor komponenty použít pro předání závislostí z kontejneru. Komponenta je automaticky připojená k předkovi (a presenteru) pokud jí vrátíš z metody createComponentXXX(). Pokud teď v konstruktoru komponenty potřebuješ presenter, přesuň takový kód do metody attached.
Komponentu která má závislosti v konstruktoru si pak zaregistruješ v configu a injectneš do presenteru kde ji potřebuješ. Best practice je pak imho ještě použít generované továrničky.