Služba na získávání parametrů – jedna superslužba, unierzální služba nebo více službiček?

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

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

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

Šaman
Člen | 2666
+
0
-

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.

Mesiah
Člen | 240
+
0
-

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

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

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

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

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

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)

Šaman
Člen | 2666
+
0
-

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?

Mesiah
Člen | 240
+
0
-

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

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

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

Tomáš Votruba
Moderator | 1114
+
0
-

Jak řešíte tuto havárii komponent?

Mesiah
Člen | 240
+
0
-

@Tomáš Votruba, nemusíš mi vykat :) Nakonec jsem přímo parametry do presenteru nenastavoval, parametry jsem předal jako argumenty továrničce komponent, kam jsem přesunul logiku, kterou jsem původně chtěl realizovat v presenteru.

Editoval Mesiah (13. 6. 2014 16:25)