Moduly – podstrčit různé třídy na různých projektech
- Jiří Nápravník
- Člen | 710
Zjistil jsem, že mám některé weby tak z 90% stejné Přešel jsem proto na to, že jsem udělal modulární aplikaci, takové menší CMS. Problém je jak řešit ty rozdílnosti, například v některé aplikaci mám nějaké dodatečné vazby mezi entitami, to je v pohodě to řeším pomocí Doctrine. Ale jak byste řešili i to samotné načtení z formuláře uložení. Upravení formuláře? Potřeboval bych nějak vymyslet, abych podstrčil pro tenhle projekt zobrazuje tenhle formulář a tohle zpracovaní. Samozřejmě ne žádné ifování, ale abych to mohl nasadit kdykoli na další aplikaci. DI umožňuje přeci podstrčit něco splňující daný interface, tak by to nějak jít mohlo, nějaké tipy?
- Oli
- Člen | 1215
Přesně tak, řešil bych to pomocí interface. Přesně kvůli tomu jsem začal hodně programovat proti interface. Dřív jsem měl konkrétní třídy, ale začal jsem používat Doctrine a když jsem potom chtěl nějakou knihovnu zpětně použít ve starším projektu, tak to byl trochu problém.
Myslím si, že interface je nejlepší cesta, ale třeba má někdo lepší řešení…
- Jiří Nápravník
- Člen | 710
Ok a muzes nahodit, jak to pouzivas v praxi? Nejak si to nedovedu predstavit jak to konfigurovat na urovni Nette…
Potreboval bych mit nejakou defaulnti implementaci. A tu pripadne prepsat. Napadlo me jen mit neco jako treba u CompilerExtension modulu treba articleService a pak CompilerExtension by mrknul, zda ji nemam nastavenou nekde v neonu, a pokud ano dal by tam tu, pokud ne, tak default…
- Oli
- Člen | 1215
Mám to zhruba takhle pro jednodušší použití
if($config['test'])
{
$mailer = $builder->getDefinition('nette.mailer')
->setFactory('\JanDrabek\MailPanel\SessionMailer');
$mailer->addSetup('\JanDrabek\MailPanel\MailPanel::register(?, ?)', array('@http.request', '@nette.mailer'));
} else
{
$builder->getDefinition('nette.mailer')
->setClass('\Nette\Mail\SmtpMailer', [$config['SMTP']]);
}
Ale neměl by být problém např. definovat si jméno služby a pokud ta služba existuje, tak ji použít jinak jinou. Nebo si předat do configu třídu, která se má použít. Uměl bych si představit něco jako
articleExtension:
form: \ArticleModule\Compoenent\Form\ThisProjectForm
a v loadConfiguration
$builder->setDefinition($this->prefix('form'))
->setClass($config['form']);
- akadlec
- Člen | 1326
Jak ty moduly registruješ? Co to dělat tak že máš základní modul, např. ArticleModule, ten umí to nejzákladnější co od něch chceš všude a pak per projekt si uděláš CustomArticleModule a ten ten původní přetíží či rozšíří. Jako službu regneš ten custom modul a máš to. Já mám třeba takto postavené rozšíření Kdyby/Doctrine o další featurky a pak v neonu neregistruju kdyby ale moje rozšíření které defakto načte kdyby + moje doplňky.
- Jiří Nápravník
- Člen | 710
@akadlec: Registruji pres flame/modules, takze tedy kazdy modul ma vlastni CompilerExtension
Nicméně ty moduly jsou komplexni, takze maji nejen modelove tridy, ale samo i presentery a sablony. Sablony nejsou problem, ty si muzu dat ven a pri vykresleni jen zkontroluji je tam nejaka vlastni sablona? Pokud ne, dam tu defaultni.
Problem je momentalne hlavne s temi modelovymi tridami. Rekneme, ze zaklad ulozi nejaky zakladni clanek. Pak mam ale clanek, ktery ma dalsi atributy a potrebuji tedy resit dalsi ulozeni. Prijde mi nejlepsi asi jak resi @Oli, a ta fasada bude implementovat interface, a nastavim tu fasadu, kterou budu potrebovat v CompilerExtension.
Ještě mě napadá nařešil jste někdo překrytí Presenteru? Podle mě to asi nějak rozumně nepůjde jelikož bych musel upravit i Router s tím související…
- Oli
- Člen | 1215
@JiříNápravník i to jsem řešil :-) Než jsem přišel na to,
že můžu presentery načítat i odjinud, tak jsem to měl vždy tak (a zatím
ještě z většiny mám), že modul měl u sebe něco jako
DefaultArticlePresenter
a v např.
app/AdminModule/ArticleModule/presenters/HomepagePresenter
byla
třída, která ten default dědila.
Ten modul si nese nějakej defaultní router, kterej se může a nemusí
použít v RouterFactory. Teprve nedávno jsem totiž zjistil, že můžu
router registrovat přímo v extension, takže tohle ještě asi nějak
předělám. Nevím teda zatím jak to funguje, ale myslím, že by zase mohlo
fungovat nějaký useDefaultRouter: on|off
a buď se ti použije
defaultní router a v RouterFactory
nic mít nebudeš, nebo si to
napíšeš v RouterFactory a defaultní router se nepoužije…
- Jiří Nápravník
- Člen | 710
@Oli díky za tip, to zní docela rozumně. I když zase teď neřeším úplně stoprocentní přenositelnost, tak jestli to není až moc velký kanon na vrabce, ale někdy jistě použiju:)
- Jiří Nápravník
- Člen | 710
@Oli dostal jsem se do faze, kdy potrebuji prekryt presenter, respektive v jednom render dostat do sablony neco navic. N
Zkusil jsem tedy jak pises ty s tim routerem, v extension si dam bud ten defaultni, nebo mu podstrcim ten upraveny. Nicmene je to jeden problem, ktery nevim jak optimalne resit. Puvodni presenter je ArticleModule\FrontModule\ArticlePresenter
ten prepsany jsem si dal sem
OverrideModule\FrontModule\ArticlePresenter
A je tu problem, kdyz volam odnekud, aby se mi vygeneroval link na ArticlePresenter, tak mam v jinych modulech samozrejem ten puvodni Article:Front:Article, coz neexistuje. Tak jsem si to udelal tak, ze v BasePresenteru prekryvam link() metodu, ktera v pripade neuspechu vygeneruje ten spravny link. Napada te neco lepsiho? Stejne tak jsem nevymyslel, zda jdou v tomhle pripade pouzivat relativni adresy k presenterum, podle me zase jen pokud bych prekryl danou metodu…
Editoval Jiří Nápravník (10. 2. 2016 4:02)
- Oli
- Člen | 1215
No já to dělám trochu jinak. Mám nějakej
DefaultArticlePresenter
a z něj (za všech okolností) dědí
ArticlePresenter
. Ten default nemá ani šablonu u sebe má jen
nějaký defaultní chování. Proto mě sedí všechny odkazy.
Tvůj případ nevím úplně jak bych řešil. Možná si do toho
ArticleModule\FrontModule\ArticlePresenter
vytáhnout informaci
jakej router je použitej a s 301 přesměrovat na
OverrideModule\FrontModule\ArticlePresenter
. Jinak mě nic
pěknýho momentálně nenapadá…
- Jiří Nápravník
- Člen | 710
@Oli aha, já myslel, tže v tom defaultu máš nějaký základ, který je použitý když nic nepřekrýváš. Zkusím se s tím nějak poprat:)
- Oli
- Člen | 1215
@JiříNápravník No to ano. Ono to je trochu schizofrenní, ale čím víc nad tím přemejšlím, tím víc se mě to asi líbí. Jde to to, že Ten default má celou logiku a je to vlastně abstraktní třída. To jsem vlastně nezmínil, protože to tak explicitně napsaný nemám, ale je to dost podstatný. A vždycky musí dědit jinej presenter.
Ten default je ve vendoru načítanej composerem (ArticleModule, PageModule, …) a drží si to, co je v 90% případů potřeba (default, detail – frontend; default, edit – admin) + nějaký drobnosti. No a v prohlížeči se k „němu“ nikdy nedostaneš, protože je abstract. Ale podědí si ho jinej presenter, kterej, pokud není potřeba nic jinýho, tak je jen prázdná třída. Ale co je důležitý, má konkrétní jméno a konkrétní šablony. Tenhle konkrétní presenter je už v app a je teda projekt od porojektu jinej. Zatímco ten default je v modulu a pro všechny konkrétní projekty je totožnej.
Tak snad jsem to vysvětlil trochu líp.
- Jiří Nápravník
- Člen | 710
Jasne uz chapu. U me je to trochu jiny, ja mam vsechny presentery stejny v tomhle pripadu a malo kdy neco pridavam. Ty projekty jsou v podstate stejny, jen obcas neco malo je treba pridat (treba ted je to jeden presenter asi tak ze 40?). Tak v tom pripade mi prijde trochu zbytecne mit 40 prazdnych presenteru.
- Oli
- Člen | 1215
Jasně, v tom případě by asi šlo mít zapnutý procházení i těch modulů a pokud se něco změní, tak odstranit ze seznamu povolených umístění presenterů ten modul a nově vytvořený presenter (se stejným názvem) vložit jinam.
Nevím jak jinak udržet modul totálně nezávislej na projektech. Taky to tak mám, že většina presenterů je prázdných a jsou tam v podstatě jen kvůli routování/rozšířitelnosti. Pokud by měl někdo lepší nápad jak to řešit, tak se taky nechám rád poučit :-)
- Martk
- Člen | 661
Moje řešení s přepsání Application (jenom zvýrazněné, ostatní je kopie Nette\Application\Application): https://github.com/…lication.php#…