Rozšiřování funkcí presenteru – komunikace více presenterů mezi sebou?

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

Ahoj, pořád se učím v Nette (pomalu, času není moc), a udělal jsem si jednoduché CMS na správu článků. Teďka chci mít možnost ke článkům přidávat fotogalerie. Administrace je mi jasná, ale co frontend část?

Abyste chápali v čem mám problém – napadlo mě řešit to několika způsoby:

  1. Rozšířit metodu renderView v ArticlePresenteru, jednoduše do něho připsat kód, který do templatu kromě článku vloží i data fotogalerie. Co ale, až budu chtít v budoucnu přidat ke článkům taky diskuzi, anketu apod.? Budu mít v ArticlePresenteru plno kódu, který se vlastně netýká článků.
  2. Vytvořit si komponentu, která bude tahat z DB galerii a pouze ji zavolám v šabloně:
<h2>{$title}</h2>
<p>{!$content}</p>
{widget gallery $id}

To bych ale zase v ArticlePresenteru musel vytvářet metodu createComponentGallery a v budoucnu i createComponentForum, createComponentPoll, … a jsme u stejného problému.

  1. Nějak zařídit, aby se při požadavku na zobrazení článku zavolal ArticlePresenter:view, vložil do šablony článek, pak aby se zavolal GalleryPresenter:view, vložil do šablony galerii a pak až se šablona vykreslila. To ale nemám páru, jestli to vůbec jde (předpokládám že ne)
  2. Nastavit ArticlePresenter, aby dědil z GalleryPresenteru, který už mu do šablony naháže informace o galerii, a ArticlePresenter tam pak už jen přidá článek. A pak v případě, že tam budu chtít přidat i hlasování a diskuzi, tak z hlasování bude dědit diskuze, z diskuze bude dědit galerie a z galerie bude dědit presenter pro články? (všechny budou k šabloné přistupovat asi v metodě renderView)

Díky za tipy a rady, od rána si nad tím lámu hlavu :-)

tomolas
Člen | 66
+
0
-

No ja by som to riesil proste tak, ze by som do presenteru jednoducho pridal 1 volanie modelu. Nieco ako

<?php
	public function renderArticle($article_id){
		$article_model = new Article();
		$gallery_model = new Gallery();
		$this->template->article_data = $article_model->getArticle($article_id);
		$this->template->gallery_data = $gallery_model->getGallery($article_id);
	}
?>

Galeriu v sablone zvladnes jednym {foreach}. A smitec! Je to odpoved na to co si sa pytal?

OK3
Člen | 91
+
0
-

Metody na vytváření komponent (diskuse, galerie apod.) si můžeš umístit do BasePresenteru, od kterého dědí ostatní presentery. Kód šablony – vykreslení komponent – pak volá tyto metody. Tak se ti nebude hromadit ani duplikovat kód v ostatních presenterch. Ber to jako poznámku k druhé části tvého navrhovaného řešení..

tomolas
Člen | 66
+
0
-

Tak to vobec neni zly napad :) Dakujem!

westrem
Člen | 398
+
0
-

Pripadne ak nechces mat BasePresenter zapratany vela metodami z roznych „modulov“ zaries to napriklad extension metodami – spravis extension pre BasePresenter na danu metodu len vtedy ked budes potrebovat.

nanuqcz
Člen | 822
+
0
-

OK3, tomolas: Jj to je přesně ono, na co jsem se ptal, díky :-)

westrem: extension metody? Najdu to někde v dokumentaci Nette? Popravdě přesně nevím, co to ta extension metoda je… ale zní to cool :-D

Filip Procházka
Moderator | 4668
+
0
-

https://doc.nette.org/…/smartobject#… tady máš Extesion metody, co se týče továrniček navrhoval bych trošku odlišné řešení

class BasePresenter extends \Nette\Application\Presenter
{

// ...

	/*=========================== Standalone Forms initialization =============================*/

	public function createComponent($name)
	{
		// prvně se kouknu jestli nemám továrničku přímo v presenteru
		$component = parent::createComponent($name);
		if ($component !== Null) {
			return $component;
		}

		// asi ne tak zkusím jestli to nesmrdí formulářem
		if ($m = String::match($name, "~^(?P<form>.+)Form$~")) {
			$ns = $this->reflection->getNamespaceName();
			// kouknu jestli náhodou nejsem v modulu, abych mohl prvně šahat po formulářích, které jsou blíž
			if (String::match($ns, "~^[^\\\\]+Module$~")) {
				$formClass = $ns . "\\Form\\" . ucfirst($m['form']);
				if (class_exists($formClass)) {
					return $component = new $formClass($this, $name);
				}
			}

			// asi žádné takové nemám, tak zkusím ještě globální
			$formClass = "\\Kdyby\\Form\\" . ucfirst($m['form']);
			if (class_exists($formClass)) {
				return $component = new $formClass($this, $name);
			}
		}
	}



	/*=========================== Common Components =============================*/

	public function createComponentNavigation($name)
	{
		return $navigation = new Kdyby\Addons\Navigation($this, $name);
	}
}

Snad je to pochopitelné, pokud máš fomulář v samostatné třídě s namespace ve tvaru

FrontModule\ForumModule\Form\Contact - největší priorita
FrontModule\Form\Contact - menší priorita
Kdyby\Form\Contact - nejmenší priorita

Tak ho to načte a vrátí jako komponentu, jenom ještě musím doladit navěšování handlerů :)
Koncept se dá samozřejmě použít i na další komponenty a můžeš si tak vytvořit konvenci pro dynamické vytváření komponent.
Je to HODNĚ magické, ale funguje to perfektně a podle očekávání :)