Pristup k promenne z url (persistentni) v modulu

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

Zdravim, mam v route definovanou promennou <lang>, ke ktere pristupuji v presenteru definovanim

/** @persistent */
    public $lang;

a pote ve funkci $this->lang. Chci se zeptat, zda-li se toho dá dosáhnout i v modelu, nejak si sahnout na promennou lang, nebo ji tam musim poslat z presenteru pri volani funkce? Diky

Editoval simPod (24. 12. 2011 13:26)

duke
Člen | 650
+
0
-

A co přesně myslíš tím modulem? Pokud myslíš komponenty (mám na mysli potomky třídy Nette\Application\UI\Control), tak tam by to mělo jít přes $this->presenter->lang.

simPod
Člen | 383
+
0
-

kecam, model

Filip Procházka
Moderator | 4668
+
0
-

Chtěl jsi napsat v modelu, ne?

Nejjednodušší bude to asi nastavit do contextu

protected function startup()
{
	parent::startup();
	$this->context->parameters['language'] = $this->lang;
}

A pak si ho vytáhnout v potřebném modelu.

Cokoliv čistějšího by bylo docela komplikované, zatím nevím jak to řešit lépe :)

simPod
Člen | 383
+
0
-

chtel jsem napsat v modelu no :)
to vypada dobre, diky

simPod
Člen | 383
+
0
-

tak jsem se zasekl. jak vytvorim v configu service parameters? a v modelu pak funguje $this->context->parameters['language']? diky

duke
Člen | 650
+
0
-

Myslím, že čistější řešení je injektovat $presenter->lang do modelu z presenteru přímo. Tj. nějak takto:

$model = $this->context->fooModel;
$model->setLang($this->lang);

Případně předávat tento parametr jen metodám, které ho potřebují.

simPod
Člen | 383
+
0
-

tohle by asi taky slo, ale to z vlozenim parametru do contextu se mi libi vic, potrebuji k tomu parametru pristupovat ve vsech modelech v 90% vsech metod, tak bych nerad pro kazdy model definoval v presenteru promennou

Nox
Člen | 378
+
0
-

Nevím jestli na to jdeš dobře

Proto se dělají factory (zjednodušení instanciace); plus předání $context už hezké DI není (jestli by rád). Přesněji se dočteš třeba na Misko Hevery, ale např. třída pak vůbec nedeklaruje své závislosti atd.

Pokud jsou třídy podobné – něměla by se použít dědičnost nebo kompozice atp.? Nevim o jaké přesně třídy jde, to už zase budeš vědět nejlépe asi sám

duke
Člen | 650
+
0
-

@simPod Z toho, jak argumentuješ, usuzuji, že by se ti možná ještě víc líbilo použít globální proměnnou $lang. Pak se nebudeš muset obtěžovat ani s injektováním kontextu do každého modelu…
Já však mluvil o čistotě řešení.

simPod
Člen | 383
+
0
-

ok dobre, ale budu potrebovat v kazdem modelu si sahnout na promennou lang routy, a abych to nemusel definovat pro kazdy model, tak se mi libilo to reseni nacpat promennou z presenteru do contextu, akorat nevim jak zaregistrovat spravne service a jak si zahnout z modelu na context kdzy do presenteru vlozim $this->context->parameters['language'] = $this->lang;

saimons
Člen | 293
+
0
-

Na tohle tema jsem otevrel nedavno jedno tema, ale nikdo moc neodpovedel, jak tohle resit. Ale z me uvahy mi plyne, ze model (at presenteru nebo komponenty) by nemel mit pristup k hodotam z url. Mel by byt predan bud kazde metode zvlast a nebo popripade pro celou tridu controlerem (presentrem). Duvod je podle me ten stejny, jaky je popsany v dokumentaci k DI o sluzbach a tovarnach.

duke
Člen | 650
+
0
-

simPod napsal(a):

ok dobre, ale budu potrebovat v kazdem modelu si sahnout na promennou lang routy, a abych to nemusel definovat pro kazdy model…

Tvůj model by měl řešit jen to, co se ho bezprostředně týká, tj. zpravidla poskytovat data, případně je nějak modifikovat, tedy nikoli routování. Model může např. umět vracet data v různých jazycích. K tomu ovšem potřebuje umět přijmout instrukci o tom, v jakém jazyce má data vracet. K tomu může sloužit např. metoda modelu setLang (jejíž význam tedy je „odteď mi vracej vše v tomto jazyce“). O tom v jakém jazyce má model data vracet by měl rozhodovat konkrétní presenter zpravidla na základě dotazu uživatele, tj. na základě parametrů (do nichž se – stejně jako do výběru onoho konkrétního presenteru – skrze routování uživatelův dotaz promítl).

simPod napsal(a):

…a abych to nemusel definovat pro kazdy model…

V presenteru budeš někde mít buď instanciaci modelu, nebo jeho získání jako služby. Co ti brání zapouzdřit tuto operaci do nějaké metody, která krom této operace provede i nastavení jazyka?

simPod
Člen | 383
+
0
-

no, kdyz volam pri jednom nacteni stranky treba 10 metod ze 2 modelu, tak mi prislo jednodusi, aby si kazdy model umel zjistit aktualni jazyk a ja mu to nemusel pokazde posilat

duke
Člen | 650
+
0
-

Pokud nechceš jazyk předávat u každého dotazu na model (u každého volání nějaké metody modelu), můžeš přeci použít výše zmíněnou metodu setLang, kterou si v modelu můžeš vytvořit a tu pak zpravidla voláš jen jednou. Navíc si tuto „konfiguraci modelu“ můžeš zapouzdřit do továrničky, kterou umístíš do nějakého BasePresenteru, takže v konkrétních presenterech už to vůbec neřešíš, tam jen tu továrničku voláš.

Z hlediska jednoduchosti není rozdíl v tom, zda jazyk nastavíš zvenčí (injektuješ), nebo zda si ho model někde obstará sám. Injektování zvenčí má výhodu v tom, že nevytváříš zbytečné závislosti, tj. vytváříš model, který je méně závislý na okolí a proto lépe udržovatelný, testovatelný, rozšiřitelný, atp. Doporučuji k přečtení kapitolu o injektování závislostí (tj. dependency injection) v dokumentaci (https://doc.nette.org/…introduction).

simPod
Člen | 383
+
0
-

vypada to zajimave, ale asi mi bude chvili trvat nez na to prijdu a skamaradim se s tim

diky

saimons
Člen | 293
+
0
-

Mohl by sem prosim nekdo uvest priklad jak dostat do modelu persistentni parametr napriklad z tovarny v BasePresenteru pomoci services v configu? Jestli je to mozne tak za pouziti auto-wiringu?

duke
Člen | 650
+
0
-

Autowiring ti automaticky dosadí pouze parametry, které jsou odkazy na jiné služby. Běžné parametry ti automaticky nenastaví. Krom toho se autowiring týká přímo třídy Nette\DI\Container, a ta neřeší, zda existuje nějaký persistentní parametr nějakého presenteru. To je zodpovědnost až toho presenteru, a ten by tedy z logiky věci měl být tím, kdo modelu hodnotu tohoto parametru sdělí.

Konkrétně to může vypadat tak, že ve třídě BasePresenter bys měl následující:

/**
 * @var string
 * @persistent
 */
public $lang;

/**
 * @return Model\FooModel
 */
protected function getConfiguredFooModel()
{
    return $this->context->fooModel->setLang($this->lang);
}

A ve FooModel.php bys měl:

/**
 * @param  string   language
 * @return FooModel provides a fluent interface
 */
public function setLang($lang)
{
    $this->lang = $lang;
    return $this;
}
saimons
Člen | 293
+
0
-

Diky za upresneni, porad jsem mel nakej takovej pocit, ze ziskani toho parametru by taky mohla byt sluzba. Prislo by by mi to pak takove prehlednejsi, ze mam sluzbu, ktera se postarta o prevzeti persistentniho parmaetru a podle DB ji prevede treba na ID (pokud „cs“ neni primarni klic) a pak se preda do tech modelu kde ji potrebuji (autowiringem). Ale je mi jasne ze ziskani toho parametru je vec presenteru.

duke
Člen | 650
+
0
-

Parametr jazyka v URL se týká view. Nette je založené na MVP (forma MVC) a ta říká, že model nemá mít přímou vazbu na view. Autowiring, o kterém mluvíš, by právě takovou přímou vazbu na view vytvořil.

Editoval duke (28. 12. 2011 18:49)