Volitelné injektování do modelu
- lukyer
- Člen | 33
Ahoj,
řeším problém, jak se vyhnout Nette\DI\ServiceCreationException:
Service ‚31‘: Class TestDI does not exist způsobené
tímto úryvkem kódu v modelové třídě:
protected $testDI;
public function injectTestDI(TestDI $parm = null)
{
$this->testDI = $parm;
}
Pokud třída TestDI fyzicky neexistuje (tzn. smažu složku s modulem), nette DI ContainerBuilder vyvolá výše zmíněnou vyjímku. Zajímavé však je, že pokud tento samý kód použiju v Presenteru, vše funguje jak má a pokud třída chybí, nic se neděje a dosadí se správně $testDI = null;
Btw inject: yes je nastaveno.
Zkoušel jsem DI kontajner všelijak debuggovat a porovnávat co je jinak v případě Presenteru a v případě Modelu ale nedodebugoval jsem se výsledku.
Díky za postřehy, případně rady jak děláte „opravdu modulární“ aplikace v Nette vy.
Editoval lukyer (14. 11. 2014 21:58)
- lukyer
- Člen | 33
@Azathoth zkusil jsem a bohužel to je trošku jiný koncept. Já potřebuju, ať se config.neon vypořádá s tím, že pokud volám setter - setTestDI(@SluzbaCoNemusiExistovat) tak pokud služba zrovna neexistuje (někdo dal DELETE na složku s daným modulem), tak dosadí NULL do argumentu tohoto setteru. Pokud ovšem služba zrovna existuje (někdo ten modul používat chce), tak dosadí službu klasicky tak jak to známe.
Je to pochopitelné? :D
- lukyer
- Člen | 33
@pawouk Díky, tímhle workaroundem by to šlo. Nicméně mi pořád jde o to, proč Presenter takovou funkcionalitu má ale Model s inject: yes ne :/. Pokud se ptáš na use-case, jedná se o logovací modul, který ve velké aplikaci může nebo nemusí být. Prostě buď se tam do složky Modules nakopíruje fyzicky nebo ne. A v jednotlivých akcích různých modelů musí být volání „zaloguj tuto akci, pokud je logovací modul přítomen“. Zkus nastínit jak bys to řešil, možná dojdeme na stejný problém :-)
- Šaman
- Člen | 2665
To mi přijde moc velká magie. Řešení stylu: „jestli najdeš něco
vhodného, tak to použij a jinak si to v tichosti udělej jinak“ zavání
obrovským WTF faktorem při hledání podivného chování programu.
Rozhodně by bylo dobré aspoň přidat řádek do configu, pokud se přidá
celý modul.
- pawouk
- Člen | 172
@lukyer: Pokud to je tak jak říkáš, tedy „zaloguj tuto akci, pokud je logovací modul přítomen“ Tak myslím, že vůbec nemusíš tu službu strkat do toho objectku, ale udělat si událost v tom oběktu a tu pak vyvolat.
// objekt do kterého jsi strkal logger původně
class Control \Nette\Object {
public $onAction;
private funcion doSomeAction(){
// tady udelas beznou akci
// a po dokonceni zavolas event
$this->onAction($this, $toCoChciLogovat); // muzes předat sám sebe, nebo to co budeš chtít logovat, to je na tobě
}
}
Pak si na tuto událost nasadit tent tvůj logger pokud je přítomen, to uděláš v ControlFactory:
class ControlFactory extend \Nette\Object {
private $container;
public function __construct(Container $container){
$this->container = $container;
}
public function create(){
$new = new Control();
if($this->container->hasService('..')) // nebo getByType to už je fuk jak to detekuješ..
$logger = $this->container->getService('servicename');
$new->onAction[] = function($control, $toCoChciLogovat) use ($logger){
$logger->log($toCoChciLogovat);
};
}
}
}