Přechod z Environment na DI pro zelenáče
- honzajavorek
- Člen | 57
Začátečník nejsem, ale pro verzi 2 očividně ano. Rád bych udělal v bootstrap.php něco takovéhoto:
require LIBS_DIR . '/Nette/loader.php';
$environment = String::webalize(php_uname('n'));
Environment::setName($environment);
A v config.ini:
[lisa < development]
; computer of Honza Javorek
variable.sizeOfPenis = "38"
database.password = "100nozka"
Dělám to tak už dlouho a je to skvělý postup, jak rozlišit různé
počítače (různé vývojáře apod.), které mají své vlastní nastavení.
Bohužel, nic jako Environment::setName()
jsem v novém Nette
nenašel a https://doc.nette.org/cs/configuring
je prázdné. Navedl by mě někdo na správnou cestu?
Jediné, co mě ještě napadlo, je mít více konfiguráků pro více počítačů. Např.:
$environment = String::webalize(php_uname('n'));
$configurator = new Nette\Configurator;
$configurator->loadConfig(__DIR__ . "/config-$environment.neon");
Jenže to mi přijde hloupé. Proč?
- Přicházím o dědičnost různých nastavení a musím udržovat několik konfiguráků (náchylnost k chybám když zapomenu).
- Autodetekce production a development je mi pak už úplně na nic, mám zcela různé konfigurace pro různé stroje.
Editoval littlemaple (11. 6. 2011 15:21)
- Patrik Votoček
- Člen | 2221
$environment = String::webalize(php_uname('n'));
$configurator = new Nette\Configurator;
$configurator->loadConfig(__DIR__ . '/config.neon', $environment);
- honzajavorek
- Člen | 57
Díky moc :) . A můžu ještě jeden dotaz? Nechce se mi zakládat nový
topic. Když využiji slavnou DI a nechci použít Environment, jak se ke
kontextu dostanu kdekoliv z aplikace? Jediné místo, kde mám možnost dostat
se ke konfiguraci nebo k přihlášenému uživateli, jsem našel v podobě
Presenter::getContext()
. Jak se k tomu ale dostanu z modelu,
z IAuthenticatoru, z komponenty, …? Pokud nechci použít
Environment::...
?
EDIT: Jde mi o nějakou best practise. Asi chápu, že se to tam má navzájem nějak všechno předávat. Z komponenty to vezmu $this->presenter->context, ale co z věcí, které jsou tak nějak vedle? Mám modelům předávat context? Co když potřebuji context v tom IAuthenticatoru, což je zase další service?
Pozn.: Absence obsahu v https://doc.nette.org/cs/configuring
je pro člověka, který se chce naučit používat to nové DI, docela
frustrující. Fórum je zanesené tunami neplodných diskusí o tom jak bude
DI v Nette vypadat, ale nejsou tu žádné funkční příklady nebo řešené
problémy. Po půldni bádání a pročítání mám chuť to zabalit a použít
buď postaru Environment
, nebo dělat užitečnější věci než
reverse engineering Nette. Snad hodinu jsem přicházel na to, že
alternativa k Environment::getVariable('bubu')
je
$presenter->getContext()->params['bubu']
.
Editoval littlemaple (11. 6. 2011 16:25)
- Vojtěch Dobeš
- Gold Partner | 1316
Asi takto, v modelové části aplikace by se nikde ke contextu
přistupovat nemělo. Docvaklo mi to při primitivní ukázce na Poslední
sobotě – vpodstatě ukázce poučky, že třídy nemají o nějakém
contextu
/DI containeru
nic vědět. Co z konfiguráku
je v modelu potřeba? Nějaká služba? Předat rovnou skrze konstruktor nebo
setter
. Data? Nejlépe opět v nějaké továrničce, třeba
statické metodě, které jediné se konfigurační container
(stejná instance jako v Presenteru v getContext()
)
předává.
Doufám, že tu nešířím bludy. Přidám ještě primitivní ukázku, oboje někde z modelových tříd, prostě mimo presentery.
# továrnička na dibi připojení
class MyDibiFactory
{
public static function createConnection(\Nette\DI\Container $cont)
{
return dibi::connect((array) $cont->params->database)
}
}
# modelová třída využívající dibi
class MyModel extends \Nette\Object
{
public function __construct(\dibiConnection $connection)
{
$this->connection = $connection;
}
}
A v config.neon
:
services:
dibi:
factory: MyDibiFactory::createConnection
model:
class: MyModel
arguments: ["@dibi"]
A úplně na závěr proč to celé? Aby se dala instance dibi
připojení jednoduše nahradit něčím jiným, třeba mockem
v testech.
Editoval vojtech.dobes (11. 6. 2011 21:25)
- nanuqcz
- Člen | 822
Komponenta: Z komponenty by to mělo jít pokud vím
$this->getPresenter()->context
Model: Pokud se potřebuješ v modelu dostat k ostatním službám, tak bys měl i ten model registrovat jako službu v DI Containeru. Věci, které z DI Containeru budeš v modelu potřebovat, mu tam předáš jako parametr.
$cont = new Nette\DI\Container;
$cont->addService('ArticlesModel', function($cont) {
$articles_model = new ArticlesModel();
$articles_model->setNecoCoPotrebuju($cont->necoCoPotrebuju);
return $articles_model;
});
P.S. V DI se teprve rozkoukávám, takže pokud jsem to napsal špatně, prosím zkušenější ať mě opraví O:-)
Editoval xxxObiWan (11. 6. 2011 16:20)
- honzajavorek
- Člen | 57
Díky, na tomto už se dá nějak stavět. Co řeším konkrétně:
- Mám v kontejneru službu Facebook, která mi poskytuje FB API. Pak mám v témže kontejneru IAuthenticator, který by ji rád využil. To mi asi ukázal xxxObiWan, díky.
- Databázové připojení. To ukazuje vojtech.dobes, díky, snad se tím proberu a pochopím to.
Samotné využití contextu v modelu teď nepotřebuju, ale měl jsem dojem, že jsem to kdysi využil (User), tak jsem se na to ptal taky. Možná je to ale špatný návrh.
Co mě dráždí:
- Jak mám vědět, co psát do config.neon? Máš tam nějaké parametry
factory, class, arguments a magické cosi
["@dibi"]
. To je někde v dokumentaci, nebo jsi použil křišťálovou kouli? Nebo mám projít řádek po řádku config parser a z toho zjistit, jaký zápis tam funguje a co dělá?
- hrach
- Člen | 1838
@vojtech.dobes: myslim, ze namas pravdu, respektive neuplnou. Model nema nic vedet o globalnim (v nette treba rekneme aplikacnim) contextu. DI vubec neznamena, ze modelu nemuzu predat jeho vlastni kontext s potrebnymi sluzbami, jako je napr. connection.
@xxxObiWan: toto „Pokud se potřebuješ v modelu dostat k ostatním službám,tak bys měl i ten model registrovat jako službu v DI Containeru.“ taky imho neni pravda. To, ze nejaka instance potrebuje nejake sluzby z ni jeste nedela sluzbu. Samozrejme, to ze model ma vlastnosti sluzby je fakt, takze tudy by ta cesta mohla vest, ale dana citovana veta neni pravdiva.
edit: spis bych to definoval tak, ze ma vedet pouze o svem vlastnim kontextu.
Editoval hrach (11. 6. 2011 16:51)
- Vojtěch Dobeš
- Gold Partner | 1316
@hrach: jasně, souhlasím. Nechtěl jsem to tím komplikovat :)
@littlemaple: počkat na dokumentaci :). Já to nějak vyčetl z examples a sandboxu, a taky určitě https://github.com/…rine-Sandbox. Stručné shrnutí:
class
: třída, která bude přímo instancovánafactory
: statická metoda, která vrátí již hotovou instanciarguments
: pole argumentů, které se v řadě předají konstruktoru (neplatí při použitífactory
, té se předá přímo instanceContaineru
). Zde se výrazy%nazevPromenne%
expandují na proměnné zconfigu
, a výrazy"@nazevSluzby"
na konkrétní služby, lze tedy jednotlivé služby skládat atd. (můj příklad výše)tags
: viz https://forum.nette.org/…cy-injectionrun: true
: zkratka protags: ['run']
Víc nevím a doufám že bludy stále nešířím.
Editoval vojtech.dobes (11. 6. 2011 21:21)
- bojovyletoun
- Člen | 667
Configurator je relativně nová část frameworku, proto bycho odkázal na téma DI ( Finalizace, Dependnency Injection, Co je Dependency Injection). Pokud nevíš, jak zapsat něco v „neon syntaxi“, použij PHP. Ostatně jak je vidět z temp/cache/Nette%5CConfigurator, tak konfigurace se kompiluje (Má na starosti Service Builder.
- honzajavorek
- Člen | 57
@vojtech.dobes Díky :)
@bojovyletoun Configurator zjevně potřebuju, pokud nechci použít Environment, od něhož mě pročítání fóra odrazuje. DI jsem pročetl, od Fabiena až po Nette Docs. To s Neon syntaxí je nepřesně řečeno – samozřejmě vím jak v ní něco napsat (http://ne-on.org/), ale tady jsem fakt nevěděl co do ní psát :)
- Tharos
- Člen | 1030
xxxObiWan napsal(a):
Komponenta: Z komponenty by to mělo jít pokud vím
Na tohle pozor, zaznelo to tu uz dvakrat a je to prave ukazkove poruseni DI. :) Ta komponenta si nema takhle sama natvrdo sahat pro nejakou zavislost, ta ji ma by dana. Idealne v tovarnicce pres konstruktor, budto formou kontaineru, anebo jeste lepe primo v podobe instanci, ktere potrebuje. Pokud formou kontaineru, Nette-way je vyroba kontaineru na miru, ve kterem bude jen to skutecne potrebne. Tj. nepredavat zbytecne ten kontainer z presenteru.
- bojovyletoun
- Člen | 667
littlemaple napsal(a):
o s Neon syntaxí je nepřesně řečeno – samozřejmě vím jak v ní něco napsat (http://ne-on.org/), ale tady jsem fakt nevěděl co do ní psát :)
Takhle jsem to myslel.
- honzajavorek
- Člen | 57
Jak změním topic? Tenhle už není moc aktuální. Hodilo by se spíš něco jako „Přechod z Environment na DI pro zelenáče“ :)
- Filip Procházka
- Moderator | 4668
Struktura, jak konfigurovat služby. A taky byjste měli začít rozlišovat mezi Dependency Injection a Dependecy Injection Containerem :) Jedno je princip, druhé nástroj, ve zkratce zde.