- arron
- Člen | 464
Ahoj,
není takový problém pomocí konfigurace změnit, která konkrétní
třída se vytváří při vytváření aplikace (Application
).
Předá se to proste jako option. Nicméně při vytváření
Application
se vytváří nový kontainer, do kterého se
předávají jen některé služby. Potřeboval bych ale do své implementace
Application
předat další služby (či možná i celý
kontainer). Nebyl by problém vytvořit novou factory metodu, ale
v originální factory jsou ještě další věci, které se provádějí či
nastavují a mě příjde blbé udělat prostý copy&paste tohoto kódu a
následnou úpravu.
Dá se tohle nějak rozumně řešit, anebo je to spíše feature request?
Díky moc
- Filip Procházka
- Moderator | 4668
To tak prostě je. Protože je to správně.
Jsem si na 87% jistý, že to co chceš udělat, nepotřebuješ udělat v
Application
.
Takže konkrétně, co potřebuješ udělat? Pokud jsi si jistý, že není
zbytí, pak koukni jak vyměňuji Application
a dosazuji služby
navíc v Kdyby.
- arron
- Člen | 464
Delas tam presne to, co jsem tu popisoval, ze mi prijde jako prasarna :-D Tohle reseni je ve stavajicim stavu velmi primocare, ale jednak duplikujes kod (coz jak vsichni vime je velmi nedobře) a jednak kdyz se zmeni implementace teto funkce v Nette (napriklad se prida nastavovani nejakeho dalsiho parametru), tak to odhalis jen v pripade, ze sledujes commit logy. Jinak se Ti nejspis aplikace zacne chovat prapodivne z neznameho duvodu:-)
Co potrebuju udelat je ve sve Application
zaregistrovat nektere
dalsi sluzby, jejich konfiguraci nacitam z databaze. Zaroven tam nacitam
z databaze routy. Na oboji by se dala napsat nejaka zvlastni trida a delat to
v bootstrapu, ale jedna to tam podle me nepatri, a jednak je to proste soucasti
te aplikace, takze poděděni a uprava Application
se mi jevi
z hlediska navrhu jako nejlepsi volba. Z toho vyplyva, ze potrebuju do sve
Application
predat minimalne nektere modely pro pristup k datum,
ze kterych pak uvedene veci builduju. Nehlede na to, ze bych nové sluzby
potreboval pridavat do globalniho containeru. Coz by se asi dalo obejit pomoci
Container::$instance
…mno asi to nebude uplne nejcistci reseni,
ale bude to primerene ciste a funkcni :-) Takze asi zatim vyreseno :-D
- Filip Procházka
- Moderator | 4668
Nepřipadá mi to jako prasárna.
- nejde to jinak
- sleduji changelog Nette docela podrobně
To jsem chtěl vědět :) Řešil bych to asi takto nějak. Popř by se dal
ještě upravit (čti: podědit a přiohnout) Configurator
, aby
tuto službu využíval přímo, nikoliv pomocí configu, což by bylo
čistější.
Editoval HosipLan (22. 7. 2011 9:26)
- Tharos
- Člen | 1030
@HosipLan: Zrovna na to koukám. Ale to přece nijak zásadně
nevadí, stačí mít svou vlastní MyApplication
(kterou autor
dotazu podle všeho už beztak má) a použít de facto ještě jednodušší
konstrukci:
Samozřejmě je pak zapotřebí nakonfigurovat aplikaci tak, aby se v továrně vytvářela instance MyApplication.
Přijde mi to jako čisté a stručné řešení bez potřeby opakování kódu.
Editoval Tharos (22. 7. 2011 13:10)
- Filip Procházka
- Moderator | 4668
Ale tím konfiguruješ kontext služby, po jejím vytvoření, to není moc pěkné.
Co uděláš až se někdo rozhodne zavolat
$application->context->freeze()
?
Tohle je dost spekulativní a je to v podstatě jedno… Podle mě je nejjednodušší to zkopírovat a upravit. Co použiješ ty, je na tobě.
- Tharos
- Člen | 1030
$application->context->freeze()
ale právě díky
protected nikdo zvenčí nezavolá.
Aby to mé řešení přestalo fungovat, musel by kontext zmrazit vyloženě
David v nějaké další verzi Nette ve výchozí
createServiceApplication
. Jiné (v úvahu připadající)
nebezpečí tam není.
Plus mám výhradu k té „konfiguraci služby po jejím vytvoření“. :) Já ten kontext nekonfiguruji až po vytvoření služby. Službu lze IMHO považovat za vytvořenou až v momentě, kdy ji vrátí tovární metoda (hlavně pak v Nette, kde se to setter injections jen hemží).
Jsem toho názoru, že mezi vytvoření služby a vytvoření instance, která službu ve výsledku reprezentuje, nepatří rovnítko.
Ale necháme to plavat, handrkovali bychom se kvůli blbostem. :)
Editoval Tharos (22. 7. 2011 13:09)
- Tharos
- Člen | 1030
Tohle je ale něco úplně jiného, než
$application->context->freeze()
. Tohle v první řadě není
zvenčí (psal jsem zvenčí, čímž jsem samozřejmě myslel mimo továrničku
a mimo třídu Application
). Tohle nepovažuji za nebezpečí
v úvahu připadající :) (proč by to někdo dělal? Tohle přece
nelze udělat ani v dobré víře). Proč by někdo psal následující
továrničku?
Podobnými postupy může pochopitelně jakýkoliv programátor kdykoliv shodit celý běh aplikace, v tom máš samozřejmě pravdu. :)
Editoval Tharos (22. 7. 2011 14:02)
- arron
- Člen | 464
Tharos napsal(a):
Chlapci, a znáte konstrukci
parent::rodicovskaMetoda()
? :) Proč neudělat jednoduše:
I to me samozrejme napadlo…co se mi na tom nelibi je to, ze v te parent metode by se uplne zbytecne vytvarel context pro aplikaci, ktery bych nasledne vymenil.
HosipLan napsal(a):
Řešil bych to asi takto nějak. Popř by se dal ještě upravit (čti: podědit a přiohnout) Configurator, aby tuto službu využíval přímo, nikoliv pomocí configu, což by bylo čistější.
Ja si prave nejsem jisty, jestli to ma byt takhle oddelene. Priprava prostedi
aplikace (routy, servisy), uplne stejne jako konfigurace konkretniho presenteru,
patri do tridy Application
. Kde bych pak ten seupper volal?
V bootstrapu? Mam takovy pocit, ze to proste do toho bootstrapu
nepatri :-)
- Tharos
- Člen | 1030
@arron: V té mé verzi se ale ten kontext nezahazuje, jen se zpřístupňuje pro přidávání služeb zvenčí a ty se pak do něj v té továrničce z hlavního kontejneru předávají. Ale už se v tomto vláknu odmlčuji, protože mé řešení nebylo shledáno hezkým :).
Editoval Tharos (22. 7. 2011 22:05)
- arron
- Člen | 464
Tharos napsal(a):
@arron: V té mé verzi se ale ten kontext nezahazuje, jen se zpřístupňuje pro přidávání služeb zvenčí a ty se pak do něj v té továrničce z hlavního kontejneru předávají. Ale už se v tomto vláknu odmlčuji, protože mé řešení nebylo shledáno hezkým :).
Oooou…sorry, uz jsem na to vecer, po 13 hodinach prace, nevidel…jop, to by (nebyt toho protected) bylo velmi solidni reseni problemu :-) A vzhledem k tomu, že si do te tridy muzu opravdu pridat co chci, tak to tak nakonec asi i udelam. Neni to mozna uplne 100%, ale ze vsech navrzenych reseni se mi to asi libi nejvic :-) Super, diky moc.
Editoval arron (23. 7. 2011 3:36)
- arron
- Člen | 464
Mno, tak jsem se k tomuhle problemu zase vratil. Cele navrzene reseni je
sice hrozne pekne, ale chybi tomu jedna malinkata drobnost:-) Kde reknu, ze
misto ´Nette\Application\Application` chci vytvorit napr.
My\Application
, ha?
Protoze mit v configu tohle:
nema sanci probehnout, protoze sluzby se v Configuratoru vytvareji jeste pred nacteni configu :-)
- arron
- Člen | 464
Tak jsem zjistil, ze mezi moji verzi Nette a tou nejnovjější se okolo
tohoto vubec nic nestalo. Takže to stále nefunguje a řekl bych, že díky
tomu, co se děje okolo tohoto
řádku ve třídě Configurator
, tak to ani fungovat nemůže
(pokud jsem tedy něco v kódu nepřehlédl). Takže otázka stále
zůstává.
- Tharos
- Člen | 1030
Mělo by Ti pomoci následující nastavení v config.neonu:
Pokud jde skutečně jen o použití vlastní třídy odvozené od Application, není vůbec zapotřebí vyrábět si kvůli tomu vlastní konfigurátor či provádět nějaké jiné čáry máry :).
EDIT: Teď ale koukám, že přesně tohle řešení už jsi zmínil. V čem konkrétně je problém? :) Vyzkoušel jsem to pro jistotu v sandboxu a samozřejmě to funguje.
EDIT 2: Už možná tuším, v čem je problém. Pozor na to, že v konfigurátoru se v té části, na kterou odkazuješ, neinstancují (fuj, hrozné slovo) služby, nýbrž se pouze do kontejneru registrují callbacky pro jejich instanciování (nevíte někdo, jak se tahle hrůza skloňuje?). Tyto „tovární metody“ přijímají parametry, které lze dospecifikovat až v config.neonu. Proto není k jejich definici „až“ v config.neonu pozdě. Tohle by mělo být to nedorozumění. Instance té Application třídy se vytváří skutečně až v bootstrapu někde na konci, tzn. v době, kdy kontejner už v sobě má patřičnou tovární metodu (používající třídu konfigurátor) a zná i její parametry nadefinované v config.neonu (a skrze ně ví, jakou třídu má vlastně instanciovat).
Editoval Tharos (31. 8. 2011 23:47)
- arron
- Člen | 464
Tharos wrote:
Pokud jde skutečně jen o použití vlastní třídy odvozené od Application, není vůbec zapotřebí vyrábět si kvůli tomu vlastní konfigurátor či provádět nějaké jiné čáry máry :).
Zaroven tam pridavam nejake dalsi sluzby, ktere vyuzivam pri inicializaci application.
EDIT: Teď ale koukám, že přesně tohle řešení už jsi zmínil. V čem konkrétně je problém? :) Vyzkoušel jsem to pro jistotu v sandboxu a samozřejmě to funguje.
To je zajimave, protoze me se to te funkce, ktera vytvari
Application
nepredaji ty parametry, ktere uvedu v configu. Zkusim
pohledat, kde presne se tam maji predavat a pak uz to snad nejak odladim…
EDIT 2: Už možná tuším, v čem je problém. Pozor na to, že v konfigurátoru se v té části, na kterou odkazuješ, neinstancují (fuj, hrozné slovo) služby, nýbrž se pouze do kontejneru registrují callbacky pro jejich instanciování (nevíte někdo, jak se tahle hrůza skloňuje?). Tyto „tovární metody“ přijímají parametry, které lze dospecifikovat až v config.neonu. Proto není k jejich definici „až“ v config.neonu pozdě. Tohle by mělo být to nedorozumění. Instance té Application třídy se vytváří skutečně až v bootstrapu někde na konci, tzn. v době, kdy kontejner už v sobě má patřičnou tovární metodu (používající třídu konfigurátor) a zná i její parametry nadefinované v config.neonu (a skrze ně ví, jakou třídu má vlastně instanciovat).
To ja vim, ze se tam v tom miste primo neinstancuji, jen se pridavaji do containeru. Ten to pak kompiluje do cache. A v te cache to prave je bez parametru (logicky, kdyz vemu v potaz umisteni toho kodu) a nenasel jsem misto, kde by se tomu pri vytvareni instance mely predavat ty parametry.
- arron
- Člen | 464
Ne ne, cache to neni :-)
Zahada vyresena…najdi rozdil:
a
(to druhe funguje:-))
S timhle by bylo potreba neco udelat, protoze si nemyslim, ze bych byl jediny, kdo si nabehne:-)
To co jsi psal v prispevku #18, tak sice preda spravne parametry,
ale nezavola se funkce z Configuratoru, takze se do Application
nedostanou vsechny potrebne sluzby a bylo by potreba to delat rucne…
Nicméně díky za pomoc, navedlo mě to kde mam hledat ;-)
- Aurielle
- Člen | 1281
Option a options je častá chyba, nicméně když jsem navrhoval sjednocení (jako u variable(s) nebo service(s)), tak to vypadá, že option bude do budoucna odstraněno.
- Vojtěch Dobeš
- Gold Partner | 1316
$context
je pouze DI\Container
.
Application
jej používá mám dojem čistě z pohodlnosti, není
třeba předávat všechny potřebné služby ručně. K takovému hromadnému
předání je použit DI\Container
, ale není to ten systémový
(který používá i klientský kód), protože je zbytečné ho do
Application
předávat, když je jasné, které služby
Application
potřebuje. Vysvětlil jsem to srozumitelně?
(například nemá smysl do Application
předávat
DI\Container
se službou dibi
, kterou si někdo
nadefinuje v config.neon
)
Editoval vojtech.dobes (7. 12. 2011 14:29)
- Filip Procházka
- Moderator | 4668
Ten context tam byl, protože se to dříve zdálo jako dobré řešení. Když se podíváte na aktuální dev, tak zjistíte, že už je dávno fuč, což je úplně nejlepší :)