Získání parametrů nastavených v bootstrapu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
dog.big
Člen | 49
+
0
-

Zdravím,
menší dotaz,
jakým způsobem v nějakém modelu získám nastavenou proměnnou?
Např. nyní potřebuji získat adresu k cache/temp, kterou sem definoval pomocí:

...
$configurator = new Nette\Config\Configurator;
$configurator->setTempDirectory(__DIR__ . '/../temp');
...
Felix
Nette Core | 1245
+
0
-

Musis tomu modelu predat nejak SystemContainer alias context, treba pres constructor a pak staci uz jen:

$context->params['xy']

Editoval Felix (14. 2. 2012 12:22)

ViPEr*CZ*
Člen | 817
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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á?

Paradiso
Člen | 101
+
0
-

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á.

22
Člen | 1478
+
0
-

@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
+
0
-

@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.

Paradiso
Člen | 101
+
0
-

22: myslel jsem to, právě tak, že se celí kontejner předávat nemá, ale když to po sobě čtu, tak jsem napsal hovadinu no :-D

duke
Člen | 650
+
0
-

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
+
0
-

@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 :-)

22
Člen | 1478
+
0
-

do konstruktoru $this nepředáš..

__construct($database, $tempDir, $service);

to už vypadá normálně, ne? :D

a ještě lépe

__construct(IConnection $database, IService $service, $tempDir);

Editoval 22 (14. 2. 2012 14:50)

duke
Člen | 650
+
0
-

@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
+
0
-

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.

Jan Endel
Člen | 1016
+
0
-

ono se stačí jen držet toho, že 90% času kód čteš a 10% ho píšeš, je lepší mít to vše na první pohled patrné. Taky se takový kód mnohem lépe testuje.

22
Člen | 1478
+
0
-

@Viper_CZ: zápis od @duke je v pořádku, lepší, než kilometrový řádek, nemyslíš?

ViPEr*CZ*
Člen | 817
+
0
-

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.

22
Člen | 1478
+
0
-

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

Editoval 22 (14. 2. 2012 17:10)

ViPEr*CZ*
Člen | 817
+
0
-

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 ;-)