Získání parametrů nastavených v bootstrapu
- ViPEr*CZ*
- Člen | 817
Do modelu si pošlete např. přes konstruktor systémový kontejner. Například takto (v Presenteru):
$model = new Model($this->context);
Poté už si v modelu může např. v konstruktoru volat toto:
public function __construct($container) {
$tempDir = $container->parameters['tempDir']; //Temp Directory
}
- nanuqcz
- Člen | 822
Ahoj, v presenteru by to mělo jít takto:
$this->context->expand('%tempDir%')
Tuto hodnotu si pak můžeš třeba předat do modelu, nebo kamkoli jinam budeš potřebovat.
EDIT: nebo jak říká Viper (jsem asi přepracovaný, to jeho je samozřejmě hezčí :-) )
$this->context->parameters['tempDir']
Editoval xxxObiWan (14. 2. 2012 12:23)
- Jan Endel
- Člen | 1016
Předávat celý kontejner je velice, velice fuj a opodstatněné jen v hrstce případů podívej se do dokumentace prvně na obecný pokec a pak nejčistší variantou bude zaregistrovat celý objekt jako službu pokud ale nechceš z nějakého důvodu registrovat model jako službu, předávej mu jen to, co potřebuje nezbytně ke svému chodu:
$model = new Model($this->context->parameters['tempDir']);
- ViPEr*CZ*
- Člen | 817
Pokud je možno jako službu, pak je to ještě lepší. Jen se zeptám zase já. Jaká je nevýhoda předat si celý kontejner (stačí nějak stručně)? Pokud potřebuju v modelu jen tuhle jednu proměnnou, pak bude asi lepší si předat jen ji. Pokud budu chtít 10 proměnných a ještě po týdnu zjistím, že bych chtěl dalších 5 (a nepůjde jen o proměnné z pole parameters), pak to budu muset stále předělávat, i když bych mohl jen brát ze systémového kontejnéru, kterej už model používá?
- 22
- Člen | 1478
@Viper_CZ: už jsi slyšlel něco o setterech? Třída, která má tolik závislostí spíš ukazuje na špatný návrh.
Paradiso napsal(a):
model by si neměl říkat o to, co chce. Pokud mu pošleš celí kontejner, tak z toho začínáš dělat „globální hodnoty“. To je základ DI. Určitě to nějaký zkušenější vysvětlí lépe, ale takhle jednoduše to chápu já.
@Paradiso: To jsi teda pěkně domotal. DI má především odstraňovat skryté závislosti, což si předáním celého containeru určitě právě zavedeš..Navíc předávat tunu balastu, kterou třída nepotřebuje, je opravdu špatné řešení.
Ze třídy by mělo být na první pohled jasné, co ke svému životu potřebuje..
Nikde není zaručené, že obsah Nette kontajneru se v budoucnu nezmění.. a pak se ti problém bude po pár měsících určitě hůře hledat.
Editoval 22 (14. 2. 2012 13:14)
- ViPEr*CZ*
- Člen | 817
@22: Ze třídy by mělo být na první pohled jasné, co ke svému životu potřebuje..
S tím naprosto a bez výhrad souhlasím.
O setterech samozřejmě vím. A rozhodně bych nerad udělal z konstruktoru
jediný setter co mi do objektu nacpe přes systémový kontejner úplně vše.
Asi máš pravdu. Jen moje praxe je moc malá, abych teď viděl co mi to
udělá za paseku.
Já přemýšlím (abych to trochu objasnil) tak, že si předám celý
kontejner a z něj si prostě hrábnu na vše… jak jednoduché na zapsání
na začátek… to bude tou leností :-)
Ono ostatně i samotný presenter má v sobě celý systémový kontejner, tak
jsem se možná nakazil odtud.
- duke
- Člen | 650
22 napsal:
@Paradiso: To jsi teda pěkně domotal. DI má především odstraňovat skryté závislosti, což si předáním celého containeru určitě právě zavedeš
Jedinou závislost vidím v tom, že počítáš s tím, že ten kontejner bude obsahovat to, co obsahovat má. A to bych nenazýval zrovna pojmem „skrytá závislost“. Pokud je závislostí hodně, může být praktičtější je předat v nějakém kontejneru (neříkám, že to má být ten systémový, ve kterém je úplně vše), nicméně souhlasím, že vysoký počet závislostí může ukazovat na špatný návrh.
Krom praktičnosti v případě většího počtu závislostí, je ale ještě jeden důvod, proč injektovat kontejner, a sice lazy loading. Nevím, jestli to už Nette umí (ještě nedávno to neumělo, ale David se vyjadřoval v tom smyslu, že o tom uvažuje), ale hodilo by se mít možnost vytahovat továrny na služby z kontejneru, aby šlo služby lazy způsobem předávat dál.
22 napsal:
..Navíc předávat tunu balastu, kterou třída nepotřebuje, je opravdu špatné řešení.
Souhlasím, nicméně nezodpovězenou otázkou zůstává, proč je tomu
tak.
Dle mého názoru je to jednak z bezpečnostních důvodů a také pro
přehlednost. Pokud má služba přístup jen k tomu, co nutně potřebuje,
nemůže např. omylem programátora šáhnout tam, kam nemá, nebo zvěřejnit
data, která mají zůstat utajena, atp. Je to podobná věc, jako řeší
klíčová slova „private“, „protected“ a „public“ ve třídách.
Když všem posílám celý systémový kontejner, jakobych veškeré služby a
parametry v něm udělal jaksi globálně public.
- ViPEr*CZ*
- Člen | 817
@duke: Ono tři závislosti už přes konstruktor budou vypadat divně.
__construct($this->context->database, $this->context->parameters['tempDir'], $this->context->other_services);
Už toto není moc hezký… a přes rovnou context se mi to pohodlněji
předá… jak jsem líný… a až tu konkrétní hodnotu vzpomenu… tak si na
ní jednoduše sáhnu… vím… tady se být líný asi nevyplatí…
červenám se.
Asi takové dva settery budou hezčí a database si rovnou předat třeba přes
konstruktor ;-) Více to napoví o daném modelu, když by to měl někdo po
mě luštit :-)
- duke
- Člen | 650
@ViPEr*CZ*: Nevím, proč by měly být settery lepší. Pokud ti jde o to, že řádek je příliš dlouhý, můžeš ho klidně napsat takto:
$service = new SomeService(
$this->context->database,
$this->context->parameters['tempDir'],
$this->context->other_services
);
Settery používám jen tehdy, když jde o volitelný (upřesňující) parametr, který není nezbytný pro funkčnost služby. Pokud jde o nezbytnou vazbu na jinou službu, vždy používám konstruktor. Má to své výhody.
Nicméně případ, který uvádíš, by bylo lepší řešit už v configu:
common:
services:
jmenoSluzby:
class: SomeNamespace\SomeService(@database, %tempDir%, @anotherService)
A v presenteru pak jen:
$service = $this->context->jmenoSluzby;
- ViPEr*CZ*
- Člen | 817
Jak jsem psal výše, tak si to dát do konfigu je Ok, s tím také
souhlasím.
Ta konstrukce s tím, že si každý parametr dám na nový řádek není
úplně šťastná. Co píše @22 na můj příspěvek je logické. Já
to totiž blb hodil do samotné __construct metody. Samozřejmě jsi to napsal
správně jak by vypadal zápis konstruktoru. Ale inicializace (vytvoření)
objektu, by pak už vypadala tím mojím zápisem, kde by jsi musel takto
předat parametry.
Aby jsme to nějak shrnuly. Myšlenka návrhu objektu (třídy) je lepší
tímto stylem a v konstruktoru je lepší si předat
3 parametry namísto jednoho (a to celého kontejneru). A asi
je mi jasné co jste mi chtěli předat a to, že zápis bude sromizitelnější
a na první pohled je vidět, které zdroje model (služba) potřebuje pro svůj
běh.
Asi jsem to již tedy pochopil správněji. A bude lepší nebejt línej
v tomto případě a raději se s tím vypsat.
- ViPEr*CZ*
- Člen | 817
22 napsal(a):
@Viper_CZ: zápis od @duke je v pořádku, lepší, než kilometrový řádek, nemyslíš?
Já vím… nemám s tím problém. Proto jsem na to také poukazoval, že díky takovému zápisu roste délka toho řádku. Já to takhle taky používám. Asi jsi mě jen špatně pochopil z psaného slova.
- ViPEr*CZ*
- Člen | 817
22 napsal(a):
ViPErCZ napsal(a):
Ta konstrukce s tím, že si každý parametr dám na nový řádek není úplně šťastná.…možná jsem tedy špatně pochopil
Jj… omlouvám se… myšleno tak, že to je dobrá konstrukce. Ostatně důkazem toho byť zápis vytvoření pole například, kdy inicializuješ a je tam vícero hodnot, tak co řádek to hodnota. To samozřejmě používám jak jsem psal. Zajímalo mě právě ale, v čem je lepší si dát práci a předávat třeba 3 konkrétní parametry ze systémového kontejneru například do modelu. A myslím, že jsem se to dozvěděl od většiny guru, což je pro mě přínosné. Stále se učím ;-)