DB model – service alebo factory
- Tomas P
- Člen | 27
Ahoj,
toto je fakt hlupa otazka, ale fakt netusim co je spravnejsie.
Viem co je factory a viem co je service. Ale netusim ci je lepsie mat DB model ako factory alebo service. Alebo je to uplne fuk, dolezite je ze sa k tomu da dostat (cez kontext alebo Environment). (… alebo je mozne to nejak dorucit do presenteru/komponenety s DI?). Tiez som videl tu ze to nemusi byt ziadne z nich a instanciovat model priamo kde ho potrebujeme, ale to asi nebude uplne koser riesenie.
Pripojenie databaze je jasny service – pri prvom pristupe sa pripoji a potom sa pouziva.
Nette\Database modely dedia od Selection – a v quickstarte to je factory … ak kazda jedna instancia je konkretny vyber z tabulky, tak ano, je to na factory.
Ale s Dibi je to inak. Tam to nededi od nicoho, konstruktor si ulozi DibiConnection (s DI a autowiring), a az jednotlive funkcie vracaju nejake data. To vyzera na service, ale pride mi to trosku divne, mat tolko servicov, z kolkych tabuliek chcem selektovat. Da sa to este nejak pospojovat do nejakych celkov, ale tiez neviem ci je to spravne riesenie. Ako riesit napr nejaky komplexnejsi select krizom cez 4–5 tabuliek, do ktoreho modelu to dat?
Dajme tomu, ak by som chcel robit nejaku (vacsiu) aplikaciu s Dibi, je to spravny pristup? (co tabulka to service)
- ViPEr*CZ*
- Člen | 817
Když víte co je factory a co je service, pak se snad ani nemůžete ptát.
:-D
Jen čistě náhodou … selským rozumem. Kdyby jste věděl co je service, pak
ji nemůžete používat na každej model, protože její instance se udělá
ať jste kde jste v aplikaci, i když jí zrovna nepotřebujete.
Přesně na service se hodí například Connection na databázi, protože tu
využijete prakticky všude. Proto taky QS používá factory na modely ;-)
Editoval ViPEr*CZ* (4. 9. 2012 20:02)
- Filip Procházka
- Moderator | 4668
Všechno co jde, tak nacpi do DI Containeru, i kdybys tam měl mít 1000 služeb.
DIC továrničky nepoužívej, raději si „ručně napiš“ factory jako službu
A QS byl aktualizován aby nevyužíval DIC továrničky. Bude ale ještě jednou aktualizován, aby používal inject*()
Editoval HosipLan (4. 9. 2012 20:21)
- miler
- Člen | 75
Tak jsem zase trochu zamotaný. Když jsem navrhoval model podle QuickStartu poprvé, dědil od Selection. Poté se Quickstart trochu změnil na to, že modely dědily od Nette\Object a vytvářely se jako továrničky.
Teď jsem v tomto topicu zjistil, že je QuickStart trochu změněný a posunulo se to do služeb.
V configu aktuálního QuickStartu je třída TaskList\Tasks zaregistrovaná jako služba se jménem tasks a v presenteru se pak do privátní proměnné ukládá ve startupu. Já jsem to měl v konstruktoru, kam jsem předal kontext a z něj jsem ukládal.
Můžete mě prosím někdo vymotat jak se tedy služby mají správně předat do presenteru? Ve startupu, v konstruktoru nebo v inject?
Omlouvám se za hloupé dotazy, ale opravdu jsem se ztratil a děkuji těm, kteří se mnou budou mít trpělivost.
// class HomepagePresenter
/** @var TaskList\Tasks */
private $tasks;
protected function startup()
{
parent::startup();
$this->tasks = $this->context->tasks;
}
Editoval miler (4. 9. 2012 21:50)
- mkoubik
- Člen | 728
Pokud máš aktuální nette (2.0.5, nebo 2.1-dev), tak použij
inject*()
– vyhneš se problémům při dědičnosti. Pokud
máš starší nette, tak si služby předej jako závislost do konstruktoru.
Pak existuje ještě setContext()
.
Jinak $this->context
je fuj a
$this->context->create*()
jakbysmet – presenter (ani jiná
služba) by neměl vůbec vědět že nějaký kontejner existuje (v presenteru
je kvůli zpětné kompatibilitě) a mělo by ho být možné sestavit
i ručně (třeba v testech).
Edit: S tím contextem ve startup()
ti to bude taky fungovat,
ale není to tak pěkný. Nicméně předělávat to asi nemusíš.
Editoval mkoubik (4. 9. 2012 21:49)
- pg
- Člen | 8
mkoubik napsal(a):
Jinak
$this->context
je fuj a$this->context->create*()
jakbysmet – presenter (ani jiná služba) by neměl vůbec vědět že nějaký kontejner existuje (v presenteru je kvůli zpětné kompatibilitě) a mělo by ho být možné sestavit i ručně (třeba v testech).
Trochu off topic možná, ale co když mám továrničku na vlastní Message
a potřebuji volat $this->context->createMessage()? Jak jinak to jde
zavolat z presenteru? I v dokumentaci je $container->create*().
A v presenteru je container $this->context
, pokud se
nemýlím.
Editoval pg (4. 9. 2012 23:46)
- Tomas P
- Člen | 27
HosipLan napsal(a):
Všechno co jde, tak nacpi do DI Containeru, i kdybys tam měl mít 1000 služeb.
OK, takze sluzby
DIC továrničky nepoužívej, raději si „ručně napiš“ factory jako službu
A QS byl aktualizován aby nevyužíval DIC továrničky. Bude ale ještě jednou aktualizován, aby používal inject*()
Dik za info, to je dobre vediet…
…
Tak som skusil update na 2.0.5, pouzivam inject*() – to funguje pekne na presenteroch.
Na vlastne FooControl (od Nette\Application\UI\Control) je ale potrebne inject* volat sam z presenteru, z funkcie createComponentFoo() – je to tak? alebo existuje nejaka automaticka alternativa? (Do presentru sa to dostane uz cez wiring automaticky.)
OT: Celkovo mi pride (IMHO), ze na kazdej stranke sice mozem mat kopu komponent (UI\Control), ale nie su vobec samostatne, takze aktualny presenter (alebo jeho predok) s nimi musi byt dost previazany.
Dalsia otazka by bola:
Ako riesit napr nejaky komplexnejsi select krizom cez 4–5 tabuliek, do ktoreho modelu to dat?
Editoval Tomas P (5. 9. 2012 10:50)
- David Ďurika
- Člen | 328
pilec napsal(a):
Ako riesit napr nejaky komplexnejsi select krizom cez 4–5 tabuliek, do ktoreho modelu to dat?
Záleží na situaci, ale přehodnotil bych pohled tabulka = model, vždy to neplatí.
presne! niekedy ma model jednu tabulku niekedy viac a niekedy ani jednu…
- Filip Procházka
- Moderator | 4668
IMHO bys měl parametry mít obalené nějakou službou, jejíž chování ta nastavení budou měnit. Tu si pak injectneš snadno.
- vvoody
- Člen | 910
Parameters cez inject nedostanes (tento sa riesi) ale moj nazor je, ze do presenteru ani netreba ziadne parametre predavat. Tak ako napisal HosipLan „i kdybys tam měl mít 1000 služeb“ a do sluzieb tie parametre predavat mozeme.
Skus si jednoducho poziadat cez injectRequest(Nette\Http\Request $request)
- miler
- Člen | 75
Díky, takhle jsem o ten Request pořádal a funguje to. Jen jsem si nebyl jsitý jestli to tak je správně.
Params jsem chtěl původně kvůli tomuto:
$this->httpRequest = $context->getService('httpRequest');
$this->httpRequest->detectLanguage($context->parameters['acceptedLangs']);
Ale to už nebudu devastovat původní topic. Děkuji moc za vaše poskytnuté rady a ukázky kódu, jak se teď mění některé postupy tak jsem byl přeci jen trochu zmaten :-)
- mkoubik
- Člen | 728
(píšu z hlavy)
class LanguageDetectionService {
private $acceptedLangs;
private $request;
public function __construct(\Nette\Http\Request $request, $acceptedLangs)
{
$this->request = $request;
$this->acceptedLangs = $acceptedLangs;
}
public function detectLanguage(array $langs = null)
{
if ($langs === null) {
$langs = $this->acceptedLangs;
}
return $this->request->detectLanguage($langs);
}
}
config.neon
:
services:
languageDetection: LanguageDetectionService(..., %acceptedLangs%)
presenter:
public function injectLanguageDetection(\LanguageDetectionService $languageDetection)
{
$this->languageDetection = $languageDetection;
}
...
$this->requestService->detectLanguage();
Editoval mkoubik (5. 9. 2012 17:07)
- raketoplan2005
- Člen | 147
Můžu přidat také svou trošku začátečnických dotazů? Používám NetteTranslator od Tomáše Votruby z kuchařky (https://componette.org/search/?…).
Služba je v configu zaregistrovaná takto:
services:
translator:
factory: NetteTranslator\Gettext::getTranslator
setup:
- addFile(%appDir%/lang, frontend)
- NetteTranslator\Panel::register
Injectuji takto:
public function injectTranslator(NetteTranslator\Gettext $translator) {
$this->translator = $translator;
}
Je to správně?
Editoval raketoplan2005 (5. 9. 2012 19:16)
- Ivorius
- Nette Blogger | 119
Podle návodu Inject Autowire
public function injectTranslator(\NetteTranslator\Gettext $translator) {
if ($this->translator) {
throw new \Nette\InvalidStateException('Translator has already been set');
}
$this->translator = $translator;
}