Moduly – podstrčit různé třídy na různých projektech

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Moje řešení s přepsání Application (jenom zvýrazněné, ostatní je kopie Nette\Application\Application): https://github.com/…lication.php#…