Služba na získávání parametrů – jedna superslužba, unierzální služba nebo více službiček?
- Mesiah
- Člen | 240
Ahoj,
řeším spíše ideologické dilema – potřebuji získávat data
z config souboru, jde o data typu: výchozí URL, výchozí počet prvků na
stránce, …
Zatím jsem to řešil stylem – co parametr, to služba, která jej vrací,
ale když jsem přidal 3. parametr tak už mi to přišlo divné – píšu
v podstatě stejný kód stále dokola.
Jaký máte, v obecném měřítku, přístup k přístupu dat z configu?
Jedna univerzální služba, jedna superslužba co umí vracet vše, nebo co
parametr to služba?
- Honza Marek
- Člen | 1664
Ani jedno. Ideální je psát kód tak, aby kód vyžadující parametry nebyl v presenterech, ale ve třídách, které zaregistruješ jako službu. A do těch služeb se pak parametry dají injektovat úplně normálně bez dalších prostředníků.
- Mesiah
- Člen | 240
Honza Marek napsal(a):
Ani jedno. Ideální je psát kód tak, aby kód vyžadující parametry nebyl v presenterech, ale ve třídách, které zaregistruješ jako službu. A do těch služeb se pak parametry dají injektovat úplně normálně bez dalších prostředníků.
Chápu-li tě správně, tak například Visual Paginator, který je součástí Nette Utils bych měl obalit do služby, které bych předat výchozí počet prvků na stránce a v komponentě nepracovat přímo s Paginatorem, ale s touhle obalující službou..?
Šaman napsal(a):
Však do presenterů se dají parametry předávat taky pomocí configu, ne? V každém případě by měla třída parametry dostat zvenku, ne si je lovit sama. To už máš jedno, jestli je lovíš globální službou, nebo přes
$presenter->getParameters()
, tak jako tak je to špageťák.
Mohl bys mi prosím napsat snippet kódu, jak můžu parametry předat preseneteru? Jde mi o to, jestli se to řeší v config.neon nebo v konstruktoru presenteru – mimochodem, kontruktor presenteru není nedoporučeno jej používat a raději se mu vyhnout..? Pokud kontruktor – jaký mají parametry interface?
- Šaman
- Člen | 2666
Řešení jsem hodil na
Gist.
Tady samozřejmě není žádný interface, takže nám nepomůže autowiring,
musíme si ten parametr skutečně předat ručně na úrovni DI kontejneru,
takže to zapíšeme do configu.
Službu lze samozřejmě i pojmenovat, já jsem uvedl nejkratší zápis,
který znám. Pojmenovaná by vypadala takto, zdá se mi to
i přehlednějši zápis:
services:
HomePagePresenter:
class: App\Presenters\HomepagePresenter
setup:
- setParam(%param%)
P.S. Do čehokoliv jiného, než presenteru by se to mělo předávat pomocí konstruktoru, pak by stačil kratší zápis:
services:
- NS\ClassName(%param%)
- Mesiah
- Člen | 240
Šaman napsal(a):
Řešení jsem hodil na Gist.
Tady samozřejmě není žádný interface, takže nám nepomůže autowiring, musíme si ten parametr skutečně předat ručně na úrovni DI kontejneru, takže to zapíšeme do configu.
Službu lze samozřejmě i pojmenovat, já jsem uvedl nejkratší zápis, který znám. Pojmenovaná by vypadala takto, zdá se mi to i přehlednějši zápis:services: HomePagePresenter: class: App\Presenters\HomepagePresenter setup: - setParam(%param%)
P.S. Do čehokoliv jiného, než presenteru by se to mělo předávat pomocí konstruktoru, pak by stačil kratší zápis:
services: - NS\ClassName(%param%)
Super, díky. Parkrát jsem narazil na setter inject do presenteru, ale zatím jsem jej nikdy nepoužil, takže si často neuvědomím, že je možné řešit věci přímočařeji…
- Šaman
- Člen | 2666
On každý injectFoo($foo)
je vlastně setter, jen takto
pojmenovaný setter si DI kontejner najde a zkusí nad ním provést autowiring
(to aktuálně platí jen pro presentery). A je to i důvod, proč se tenhle
setter z ukázky nemůže jmenovat injectParam
, protože by DIC
nadával, že nemá hint podle kterého by autowiring provedl.
Jinak popsaný způsob lze použít všude, je to obecný zápis služby, která
potřebuje dodatečně nakonfigurovat (třeba předat volitelně cache). Jen je
málo známý fakt, že v Nette >2.0 lze presenter vytvořit jako
obyčejnou službu a ta se použije. Když taková není, vytvoří se presenter
pomocí PresenterFactory.
- Patrik Votoček
- Člen | 2221
Můžeš v klidu a bez problémů použít:
services:
- App\Presenters\HomepagePresenter(%param%)
Ad konstruktor injection v Prseneterech je to pořád preferovaná cesta jak
do presenteru dostat závislosti. Pouze u abstraktních / base presenterů se
používají injectMetody
/ @inject
kvůli
konstruktor hell.
- Mesiah
- Člen | 240
Pánové díky za podměty!
Patrik Votoček napsal(a):
Můžeš v klidu a bez problémů použít:
services: - App\Presenters\HomepagePresenter(%param%)
Ad konstruktor injection v Prseneterech je to pořád preferovaná cesta jak do presenteru dostat závislosti. Pouze u abstraktních / base presenterů se používají
injectMetody
/@inject
kvůli konstruktor hell.
Díky za tip ohledně abstraktního base presenteru, ten teď zrovna řeším
a k tomu abych mohl nastavit parametry přes neon, nemůže být BasePresenter
abstraktní (ve výchozím nastavení je) a ptám se sám sebe: skutečně to
chci?
Může mě to v budoucnu přinést nějaké trápení? Po tom, co jsem
‚abstract‘ odstranil mám takový ten pocit, jako když vyjdete z bytu do
města a začnete přemýšlet, jestli jsem nezapomněl vypnout
žehličku…
Edit: důvod proč používám BasePresenter je ten, že jde o parametr verze a ten se vypisuje na každé stránce a psát na to samostatný Control mi přijde přehnaný…
Editoval Mesiah (31. 5. 2014 19:09)
- Mesiah
- Člen | 240
Šaman napsal(a):
No, neabstraktní BasePresenter sice můžeš vytvořit přes config, ale jako samostatnou entitu. Nějaký
FooPresenter extends BasePresenter
už ten parametr předpokládám nebude mít nastavený, nebo ti to funguje?
Upřimně, moc nerozumím na co se ptáš, ale konkrétně jde o parametr
version
, Neon mám nakonfigurovaný takto:
basePresenter:
class: App\Presenters\BasePresenter
setup:
- setVersion("%version%")
- setUsersData("%profiles%")
a pak klasika – mám (public) slot $version v base presenter a setter, jenže problém je, že hodnota slotu version je při dumpu NULL…
class BasePresenter extends Nette\Application\UI\Presenter
{
/**
* @var string
*/
public $version;
/**
* @var string
*/
public $usersData;
public function setVersion($version) {
$this->version = $version;
}
public function setUsersData($data) {
$this->usersData = $data;
}
}
kde dělám chybu?
- Šaman
- Člen | 2666
Však o tom mluvím. Ty přece nepotřebuješ BasePresenter, ale
FooPresenter extends BasePresenter
, ne? A ten jsi
nenakonfiguroval. Ty máš nakonfigurovanou instanci
BasePresenteru, která ti je k ničemu.
V tomhle připadě budeš muset buď nastavit ten parametr u všech
presenterů, nebo si ho v BasePresenteru potichu vytáhneš z kontejneru.
Editoval Šaman (1. 6. 2014 22:28)
- Mesiah
- Člen | 240
Šaman napsal(a):
Však o tom mluvím. Ty přece nepotřebuješ BasePresenter, ale
FooPresenter extends BasePresenter
, ne? A ten jsi nenakonfiguroval. Ty máš nakonfigurovanou instanci BasePresenteru, která ti je k ničemu.
V tomhle připadě budeš muset buď nastavit ten parametr u všech presenterů, nebo si ho v BasePresenteru potichu vytáhneš z kontejneru.
Omlouvám se, nedošlo mi to… :(
Takže pokud bych chtěl ten parametr zobrazovat na všech stránkých, tak
jediný rozumný přístup je vytvořit si na to komponentu, viď?
Mimochodem, když jsem zmínil ty komponenty, tak jediný způsob, jak bych mohl do generované továrničky dostat parametr je zhruba tento zápis..? (nemůžu momentálně vyzkoušet)
services:
- implement: IVersionFactory
setup:
- setVersion(%version")
Editoval Mesiah (2. 6. 2014 7:59)