Jak přidat služby do basePresenteru

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

Dobrý den, udělal jsem si komponentu ankety, která přijímá model, httpRequest a httpResponse. Továrničku vytvářím a plním v presenterech pomocí inject metod, například takto:

<?php
	/** @var Nette\Http\Response */
	private $httpResponse;

    public function injectHttpResponse(Nette\Http\IResponse $httpResponse)
    {
        $this->httpResponse = $httpResponse;
    }
?>

A to pak předávám do továrničky na tu anketu a funguje to tak jak má.

Chtěl bych to ale použít v basePresenteru, abych to nemusel vytvářet v každém presenteru, když to chci generovat na všech stránkách. Když to tam ale dám, tak mi to nefunguje. Můžu se zeptat proč?

Do layout.latte se to pak snažím předávat v metodě beforeRender, ale v tom problém není.

Hafran
Člen | 121
+
0
-

No a máš ty presentery v kterých to pak používáš dědící od Basepresenteru?

Siam
Člen | 54
+
0
-

Hafran: teď jsi mě trochu zmátl tím, že se na to vůbec ptáš. Používám klasickou strukturu z nette sandboxu, takže třídy prezenterů mají klasický zápis třeba FooPresenter extends BasePresenter. Takže dědí, nebo ne?

huttarichard
Člen | 4
+
0
-
private $httpResponse;

měl by si zaměnit za

protected $httpResponse;

Private platí pro danou třídu, nikoliv pro třídy co jí dědí :) Protected umožnuje přístup!

Editoval huttarichard (15. 10. 2012 14:47)

studna
Člen | 181
+
0
-

Pomohlo by, kdybys uvedl chybovou hlášku nebo co vlastně nefunguje. Případně celý kód, jak sestavuješ tu komponentu. Nevykresluješ ji přes {control}?

Do layout.latte se to pak snažím předávat v metodě beforeRender, ale v tom problém není.

Možná saháš do BasePresenteru po private proměnné.

MartinitCZ
Člen | 580
+
0
-

Spíš bych se zamyslel na použítím. Když chceš injectovat v BasePresenteru (tedy tahat to i tehdy, nebudeli třeba), tak to už skoro můžeš rovnou použít services locator ($this->context->httpResponse).

Siam
Člen | 54
+
0
-

Já akorát hledám způsob jak to udělat. Měl jsem za to, že se to nebude tahat ikdyž to není potřeba. Potřebuje prostě dostat do továrničky nějak model, httpResponse a httpRequest, abych tam s nimi mohl pracovat.

Že nefunguje ten httpRequst, response a model zjistil tak, že jsem si nechal vypsat v šabloně nějaký string co jsem si zadal do basePresenteru pomocí beforeRender and this->template a ten string pak zkusil nahradit třeba $this->httpRequest->getRemoteAddress() a nevypsalo to nic.

Pokud to všechno předávám v normálním presenteru, tak všechno funguje.

Přes control jí vykresluji a protected jsem zkoušel také nastavit a nic.

Továrničku používám takovouto:

<?php
    protected function createComponentPoll()
	{
        $control = new pollControl();
        $control->setQuestionId(2);
        $control->setHttpRequest($this->httpRequest);
        $control->setHttpResponse($this->httpResponse);
        $control->inject($this->model);
		return $control;
	}
?>

Ale jak jsem psal komponenta funguje normálně, akorát nevím jak jí předat ty věci jinak než extra z každého presenteru.

Filip Procházka
Moderator | 4668
+
0
-

Http\Request a Http\Response jsou přístupné v presenteru by default

class FooPresenter extends BasePresenter
{
	private $polls;
	private $questionId;

	public function injectPoll(MyApp\Polls $polls)
	{
		$this->polls = $polls;
	}

	public function actionDefault($pageId)
	{
		// tohle jsem si vymyslel, doplň vlastní logiku
		$this->questionId = $this->polls->findPagePoll($pageId);
	}

	protected function createComponentPoll()
	{
		$control = new PollControl($this->polls);
		$control->setQuestionId($this->questionId);

		// nechápu na co tohle potřebuješ, ale budiž
		$control->setHttpRequest($this->getHttpRequest());
		$control->setHttpResponse($this->getHttpResponse());

		return $control;
	}

}
class PollControl extends Nette\Application\UI\Control
{
	private $polls;

	public function __construct(MyApp\Polls $polls)
	{
		parent::__construct();
		$this->polls = $polls;
	}

	// ...
}

Editoval HosipLan (15. 10. 2012 17:57)

Siam
Člen | 54
+
0
-

HosipLan:
díky za odpověď. S tím upozorněním na to, že jsou ty dvě služby default jsi mi dost pomohl. :)

Ten request a response tam chci kvůli zjištění IP adresy a práci s cookies. A pochopil jsem to tak, že je lepší to tam předat nějakým seterem z venku, než si to tahat z nějakého globálního prostoru. Pochopil jsem to blbě? Nebo ti jde o to, že práce s IP a cookies patří do modelu? On s nima vlastně pracuje model, ale protože jsem nevěděl jak zprovoznit v modelu ten request a response, tak jsem to předal z presenteru do komponenty a z komponenty do modelu, což je asi hodně špatné, ale nevěděl jsem jak to tam jinak zprovoznit.

Filip Procházka
Moderator | 4668
+
0
-

Práce se sušenkama do komponent a presenterů určitě patří. Ale v modelu může být také, pokud je to vhodné :) A tady to docela vhodné je.

A pochopil jsem to tak, že je lepší to tam předat nějakým seterem z venku, než si to tahat z nějakého globálního prostoru.

To je velice správně!

On s nima vlastně pracuje model, ale protože jsem nevěděl jak zprovoznit v modelu ten request a response, tak jsem to předal z presenteru do komponenty a z komponenty do modelu.

To už tak super není. Měl by sis je vyžadovat v konstruktoru

class Polls extends Nette\Object
{
	private $httpRequest;
	private $httpResponse;
	private $db;

	public function __construct(
		Nette\Database\Connection $db,
		Nette\Http\Request $httpRequest,
		Nette\Http\Response $httpResponse)
	{
		$this->db = $db;
		$this->httpRequest = $httpRequest;
		$this->httpResponse = $httpResponse;
	}


	// nejake tvoje metody

}

Nette pak samo koukne do konstruktoru a uvidí, že vyžaduješ tyhle 3 třídy. Takže pokud budou registrované jako služby, tak ti je tam předá automaticky. Což nejspíš jsou.

services:
	polls: Polls # nazev sluzby dvojtecka nazev tridy

Presenter a komponenta se nám pak zjednodušší

class FooPresenter extends BasePresenter
{
	private $polls;
	private $questionId;

	public function injectPoll(MyApp\Polls $polls)
	{
		$this->polls = $polls;
	}

	public function actionDefault($pageId)
	{
		// tohle jsem si vymyslel, doplň vlastní logiku
		$this->questionId = $this->polls->findPagePoll($pageId);
	}

	protected function createComponentPoll()
	{
		$control = new PollControl($this->polls);
		$control->setQuestionId($this->questionId);
		return $control;
	}

}

class PollControl extends Nette\Application\UI\Control
{
	private $polls;

	public function __construct(MyApp\Polls $polls)
	{
		parent::__construct();
		$this->polls = $polls;
	}

	// settery už nepotřebuješ
	// render a signály
}

Editoval HosipLan (16. 10. 2012 11:23)

Siam
Člen | 54
+
0
-

Díky moc Filipe, zkusím se s tím nějak poprat a předělat to.

Nemůžeš mi prosím tě ještě poradit v tomto zapomenutém tématu?

Siam
Člen | 54
+
0
-

HosipLan:
udělal jsem to jak si psal (ještě jsem přidal do třídy polls namespace MyApp) a při renderu v komponentě mi to vyhazuje laděnku „cannot read an undeclared property MyApp\Polls::$httpRequest.“.

Ten httpRequest jsem volal v té komponentě jako $this->polls->httpRequest->getCookie… To, je správně, že? Nevíš v čem by mohla být chyba?

Filip Procházka
Moderator | 4668
+
0
-

Pokud tam máš private, tak se k tomu dostaneš pouze zevnitř třídy. Raději bych to co si hraje s těmi sušenkami nějak osekal/rozpůlil a udělal si metodu v Polls.

Siam
Člen | 54
+
0
-

HosipLan:
Už mi to jde, jupí. Měl jsem bordel v názvech proměnných, moje blbost. Díky moc za pomoc!

Chtěl bych nějak zabránit aby nehlasovali boti a napadlo mě, že bych povolil hlasování jenom lidem co mají zapnuté cookies. Nepřišel jsem ale na to, jak ověřit, jestli to mají zapnuté, nebo ne. SetCookie vypadá, že false v případě neúspěchu nevrací a nevím, proč, ale nešlo mi ani zapsání cookies a pokus o jeho načtení s tím, že když se to podaří, vrátí to TRUE a to povolí v další metodě zápis do DB.

Existuje v nette nějaký elegantní způsob jak zjistit podporu těch cookie? Případně jiné řešení detekce botů?

Tomas P
Člen | 27
+
0
-

Aby som teda zhrnul (a uistil sa ze to chapem spravne) https://forum.nette.org/…sepresenteru#…

Ma to byt takto (obecne)?:

presenter P
zavislosti na service-och sa riesia same (rovnako ako o konstrukciu presenteru sa stara nette)
staci vytvorit injectMyService(type param) a to sa zavola. V pripade ze existuje len jeden service toho typu a je zapnuty (default = true) autowire.

control C
konstrukciu aj zavislosti na service-och si riesime sami
instancia sa vytvori v P v metode createComponentC(), kde spravime c = new C(…); a c->set*()
na vlozenie service-ov, je ako pises idealne pouzit __construct(type1 service1, type2 service2, …)
IMHO ja som to doteraz robil rovnako ako v presenteroch (s inject* metodami), len som si to zavolal sam. To napr nechapem, preco nerobi nette jednotne, napr parent construktor by kludne mohol zavolat inject*() metody.

model M
konstrukciu riesi nette a autowiring
vsetky dependencie sa predavaju v __construct
dedi od Nette\Object

Otazka
Niekde som cital (na fore ale neviem kde), ze na controloch by sa nemali menit parametre konstruktoru – je to uz teraz neaktualne? resp. nemoze sa stat ze bude nieco chciet system, ze instanciu vytvori sam? (predok PresenterComponent napr. ma parametre)