Exponovat Control místo Presenteru

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

Presentery jsou v Nette nadbytečné.

Ve svém novém projektu už bych chtěl využívat výhradně controly a hledám způsob, jak exponovat controly ven (abych označil control za „root“ – tzn. obdobu dnešního presenteru) a celou aplikaci napsat v nich.

Obejdu se bez nějakého presenteru, který bude „control loader“? Respektive, je v Nette cesta, jak používat místo presenterů controly?

Filip Procházka
Moderator | 4668
+
0
-

Stačí aby tvůj Control implementovat Nette\Application\IPresenter a služba Nette\Application\IPresenterFactory ho vrátila na požádání aplikaci.

jiriknesl
Člen | 56
+
0
-

Následující kód vypíše Notice (missing basePath).

Předpokládám, že těch věcí, které má presenter a nemá defaultně control, se asi najde víc.

<?php

class HomepagePresenter extends Nette\Application\UI\Control implements Nette\Application\IPresenter
{
	private $context;
	private $template;
	private $request;

	public function setContext($context)
	{
		return $this->context = $context;
	}


	public function run(Nette\Application\Request $request)
	{
		$this->request = $request;
		$this->renderDefault();
	}

	public function renderDefault()
	{
		$this->template = $this->createTemplate();
		$this->template->anyVariable = 'any value';
		$this->template->setFIle(dirname(__DIR__) . '/templates/Homepage/default.latte');

		return new Nette\Application\Responses\TextResponse($this->template->render());
	}

}

Zkoušel někdo opravdu exponovat control a ví, jak to udělat, aby bylo použití podobně pohodlné, jako presenter?

bazo
Člen | 620
+
0
-

len tak zo zaujimavosti, preco? a ake to ma vyhody? teda, ak sa ti chce odpovedat. dik.

Filip Procházka
Moderator | 4668
+
0
-

Pravda, šablony nejsou úplně připraveny být osekány o presenter. Pohledem do kódu zjistíš, že spousta věcí se získává z presenteru, když si vytvoříš BaseControl a překryješ createTemplate nějak takto, tak by to mohlo pro začátek stačit

abstract class BaseControl extends Nette\Application\UI\Control implements Nette\Application\IPresenter
{
	/** @var Nette\DI\IContainer */
	protected $context;

	/** @var Nette\Application\Request */
	protected $request;


	/**
	 * @param Nette\DI\IContainer $context
	 */
	public function setContext(Nette\DI\IContainer $context)
	{
		return $this->context = $context;
	}


	/**
	 * @param Nette\Application\Request $request
	 * @return Nette\Application\IResponse
	 */
	public function run(Nette\Application\Request $request)
	{
		$this->request = $request;
		return $this->render();
	}


	/**
	 * @return Nette\Templating\ITemplate
	 */
	protected function createTemplate($class = NULL)
	{
		$template = parent::createTemplate($class);

		if ($this->context) {
			$template->setCacheStorage($this->context->templateCacheStorage);
			$template->user = $this->context->user;
			$template->netteHttpResponse = $this->context->httpResponse;
			$template->netteCacheStorage = $this->context->cacheStorage;
			$template->baseUri = $template->baseUrl = rtrim($this->context->httpRequest->getUrl()->getBaseUrl(), '/');
			$template->basePath = preg_replace('#https?://[^/]+#A', '', $template->baseUrl);
		}

		return $template;
	}



	/**
	 * @return Nette\Application\IResponse
	 */
	abstract public function render();
}

Nyní stačí vložit do komponenty $context a implementovat metodu render().

class HomepagePresenter extends BaseControl
{
	public function render()
        {
		$foo = $this->request->params['foo'];

                $this->template->anyVariable = $foo;
                $this->template->setFIle(dirname(__DIR__) . '/templates/Homepage/default.latte');

                return new Nette\Application\Responses\TextResponse($this->template);
        }
}

PS TextResponse rozlišuje, jestli mu předáváš šablonu.

Majkl578
Moderator | 1364
+
0
-

Rozhodně bez presenteru nebudou fungovat třeba ani odkazy, flagy requestů, kanonizace, flash message nebo responses.

Ale v důsledku, Presenter přeci Control je, tudíž výhradně controly používáš i takhle. :)

hAssassin
Člen | 293
+
0
-

Taky to moc nechamu na co to je dobry… Pokud nekdo vi, prosim, poradte, vysvetlete :)

jiriknesl
Člen | 56
+
0
-

hAssasin: Jde o to, že sémantika presenterů je nadbytečná. Presenter je Control a Control může obsahovat další Controly. Není důvod, proč by Control nemohl být označen za „root“ a tím pádem se stát presenterem.

Nakonec by pak bylo možné vytrhnout kus aplikace a udělat z něj samostatný presenter nebo naopak vzít aplikaci a zabudovat ji někam jako control.

Ondřej Mirtes
Člen | 1536
+
0
-

V Nette je blbý, že Nette\Application\UI\Presenter zařizuje spoustu věcí, který vypsal Majkl578. Krásná ukázka FRP (Five Responsibilities Principle).

Taky jsem jednou chtěl zkusit jen naimplementovat IPresenter, ale narazil jsem, protože jsem si tím odstřihl možnost používat většinu elegantních featur Nette. A taky to rozhraní lže, protože kromě metody run() je potřeba přidat i setContext :o)

Ondřej Mirtes
Člen | 1536
+
0
-

Líbilo by se mi, kdyby charakteristikou Nette\Application\UI\Presenter bylo jen spouštění životního cyklu na základě příchozích parametrů v Requestu v metodě run() (dal by se tedy přejmenovat na LifecyclePresenter, stejně jako máme MicroPresenter). Všechna ostatní funkcionalita by se dala přesunout do tříd jako LinkGenerator, Canonicalizator, FlashMessenger a dala by se znovupoužívat i v jiných kontextech – vlastních presenterech, vlastních knihovnách a frameworcích.

Taky si pohrávám s myšlenkou, že by se komponentový model nemusel řešit dědičností a komponenty by mohly být připojeny v nějakém stromu, aniž by o tom samy věděly. Architektura Nette by byla zas o něco volnější a použitelnější.

mkoubik
Člen | 728
+
0
-

Pokud vím, tak něco jako „převést dědičnost presenterů na kompozici“ je v roadmapě.

David Grudl
Nette Core | 8183
+
0
-

Ondřej Mirtes napsal(a):

Líbilo by se mi, kdyby charakteristikou Nette\Application\UI\Presenter bylo jen spouštění životního cyklu na základě příchozích parametrů v Requestu v metodě run() (dal by se tedy přejmenovat na LifecyclePresenter, stejně jako máme MicroPresenter). Všechna ostatní funkcionalita by se dala přesunout do tříd jako LinkGenerator, Canonicalizator, FlashMessenger a dala by se znovupoužívat i v jiných kontextech – vlastních presenterech, vlastních knihovnách a frameworcích.

To by se mi líbilo taky. A moc. Ale znamená to docela hodně práce a ptám se, zda se toho někdo ujme?