Co takhle fáze pro AJAX requesty?

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

Ahoj,

poslední dobou jsem si hrál s AJAXem v Nette a přišlo mi, že všude musím řešit a ověřovat, jestli se jedná o AJAX request nebo ne – a to i v případě pokud přidám nějakou hotovou komponentu – musím svůj kód kvůli ní měnit. A to samozřejmě celkem znepřehledňuje kód a když jsem se rozhodl komponentu smazat, opět jsem musel svůj kód upravit. Nakousl jsem to tady a asi jsem to ne příliš dobře vysvětlit.

Měl jsem podobný návrh stránky

Moje a oblíbené fotky (ajax) → zobrazení dalších fotek

Komentáře (ajax) → posílání příspěvků a zobrazení nových komentářů (+ třeba paginator)

Uvažuju UserPresenter a render/actionDetail

Tím, že si budu AJAXově listovat komentáře, každým kliknutím a tím vysláním AJAX požadavku se vykoná actionDetail, renderDetail a provede se všech 6 selectů (1 pnavíc pro paginator), přitom ale stačí jen 2 dotazy. Už jen pouhým přidáním paginatoru s požadavkem AJAXu musím svůj kód podmínkovat tak, aby se nevykonávaly dotazy na db při AJAXu. Úplně to samé je například při zobrazení dalších fotek. Místo 1 dotazu se jich zase pošle 6 a já to zase musím podmínkovat, ale ještě k tomu musím přidat podmínku, že nechci listovat paginatorem, … :-) No přijde mi to dost divné.

To samé bylo například u komponenty PollControl, kam jsem do komentářů napsal své řešení, které mi fungovalo tak, jak jsem chtěl. Protože při AJAX požadavku se mi opět vykonávalo to, co jsem nechtěl – chtěl jsem jen zaznamenat jediný hlas a už nepotřebuju vybírat info od uživatele, jeho fotky apod., přece jen hlasuju v anketě!

Líbila by se mi další fáze, tak jako je action, handle a render. Třeba ajaxDetail, kde by pak bylo vše v jednom místě jasně vidět, co se při AJAXu volá a mohla by být jedinou volanou fází při AJAX requestu, po které by následovalo vykreslení šablony bez volání renderDetail. Resp. lepší by bylo, kdyby došlo k vybrání snippetů ze šablon (pokud možno ze všech, i z nadřazených jako je layout) a ty se odeslaly na výstup jako JSON.

Bylo by něco takového možné? Vsadil bych se, že pokud někdo přidá na stránku (kde se vykovává více dotazů) paginator s podporou AJAXu, tak už rozlišování (non-)AJAX požadavků neudělá a to vede k neefektivnosti využití AJAXu a stává se tak docela zbytečný…

Teď jsem to snad napsal úplně srozumitelně a budu rád, když se k tomu třeba jen nějak vyjádříte.

Díky

22
Člen | 1478
+
0
-

nějak to nechápu, proč si to neuděláš přes handler → handleKomentar() treba a tim padem mas jen handle fázi, kde zinvaliduješ daný snippet + render fázi, pokud nepošleš payload.

joe
Člen | 313
+
0
-

@22: Handler na to mám, nevím jak jinak bych to dělal :), ale není pravda, že pak při volání signálu mám jen onu handle fázi, mám právě všechny tři – actionDetail, handleKomenter a renderDetail

Znamenalo by to tedy, že pokud bych chtěl AJAXovat, měl bych vše v action a render fázi obalit do podmínky if(!$this->isAjax()) { ... } protože jinak by se to s největší pravděpodobností vykonávalo zbytečně.

Pokud ale chci invalidovat snippet, musí (pravděpodobně – jiný způsob neznám) dojít k renderování. A tím, že většinou v render fázích bývá plnění šablony → volání dotazů na db (jako například getPhotos(), getFavouritePhotos() apod.), bych sem musel dát tu samou podmínku (viz výš).

Možná by stačilo, kdybych mohl odeslat payload s tím, že se vyrendruje šablona, ale nedojde k volání samotné fáze render (vím, trochu se to odporuje). Nebo spíš že by se vybraly jen ty invalidované snippety ze šablony, ty se naplnily daty a ty bych mohl odeslat do payload.

Editoval joe (29. 6. 2011 2:03)

22
Člen | 1478
+
0
-

jo, už mi to docvaklo. Původně jsem myslel, že ti jde o invalidaci snippetu, ale tobě vadí, že se v podstatě natahuje znovu stránka akorát se vymění ta část stránky, která je invalidní… a že se provede celej životní cyklus. Teda, že je to v podstatě takový šméčko, protože se natáhne všechno znova (životní cyklus).

Editoval 22 (29. 6. 2011 7:10)

joe
Člen | 313
+
0
-

že se v podstatě natahuje znovu stránka akorát se vymění ta část stránky, která je invalidní…

Tohle nevím jestli je to, o čem píšu :)

že se provede celej životní cyklus

O tohle mi jde. Protože se v něm provede úplně všechno, jakoby to AJAX request nebyl. A tak když bych chtěl třeba přes AJAX (signál) nastavit nějakou proměnnou (tzn. nepotřeboval bych vůbec db), tak i přes to, by se provedly všechny dotazy, co jsou naházený v těch různých fázích presenteru – pokud to nebude dostatečně ošetřený. Tzn. že pak ten AJAX tam je k ničemu, protože se vlastně provádí jako kdyby tam vůbec nebyl, ale jen s tim rozdílem, že se ta stránka znovu nenačte…

22
Člen | 1478
+
0
-

mno nevím, počti úvod tady.
Myslím, že v Nette je to i záměrem…

Edit: velice zajímavá je taky poslední poznámka v diskusi. Říjen se už blíží btw :-)

Editoval 22 (29. 6. 2011 7:48)

joe
Člen | 313
+
0
-

Díky za odkazy, seriál znám pomalu už nazpaměť a ten komentář, na který odkazuješ je už rok starý :-) Každopádně v tom seriálu o AJAXu jsem neobjevil nic, co by „problému“ nějak pomohlo.

Nepoužíváš AJAX na stránce, kde kromě toho, co chceš mít AJAXem, taháš i jiná data? Pak bych chtěl vidět, jak to máte kdo ošetřené :-)

Editoval joe (29. 6. 2011 8:10)

Filip Procházka
Moderator | 4668
+
0
-

Řešením je naplno využít sílu komponent. Zkus uvažovat takto:

protected function createComponentPhotos()
{
	// nevyužívá konstruktor, ale presenter si ji připojí sám
	return new PhotosControl($this->context->photos, $this->user->identity);
}
class PhotosControl extends Nette\Application\UI\Control
{
	public function __construct(MyApp\Model\Photos $photos, Nette\Security\IIdentity $identity)
	{
		parent::__construct(); // musi se zavolat! klidne i prazdne, ale musi!
		$this->template->setFile(__DIR__ . '/photos.latte');

		// ...
	}

	public function render()
	{
		$this->template->photos = $this->photos->findByUser($this->identity->getId());
		$this->template->render();
	}
}

Jediné co teď musíš dodělat je invalidace. Ale všechny dotazy se dějí až při vykreslení komponenty. Takže v presenteru máš jenom sestavení komponent (ošetření ajaxu můžeš mít i v komponentách).

Dokonce i signály můžeš mít v komponentách. Pak je ti jedno, že se provádí nějaké action a render, pokud v nich nikam nic neplníš :)

joe
Člen | 313
+
0
-

Pomocí komponenty to sice můžu mít, nicméně tam chybí to nejdůležitější

if($this->presenter->isAjax()) {
	$this->snippetMode = TRUE;
	$this->invalidateControl();
	$this->render();
	$this->getPresenter()->sendPayload();
}

Protože jinak opět dojde k volání všeho i na aktivním presenteru. Ale to není řešení. Používat komponentu jenom z toho důvodu, že používám AJAX se mi teda nelíbí, to si to raději projdu a napíšu podmínky, než vytvářet komponentu pro jednu věc ;)

Editoval joe (29. 6. 2011 8:50)

Filip Procházka
Moderator | 4668
+
0
-

V tom případě jsi vůbec nepochopil sílu Nette :)

Kdyby jsi měl všechno jako komponenty, tak ti nevadí, co se děje v presenteru.

A na tohle si můžeš napsat pomocnou metodu do nějakého basePresenteru.

public function ajaxSendComponent(Nette\Application\UI\PresenterComponent $component)
{
	if(!$this->isAjax()) {
		return;
	}

       	$component->snippetMode = TRUE;
       	$component->invalidateControl();
       	$component->render();
        $this->sendPayload();
}
public function handleMoreComments($from)
{
	$this->template->comments = $this->comments->findfrom($form, $this->identity->id);
	$this->presenter->ajaxSendComponent($this);
}

Je to nástřel… neřeším implementační detaily…

joe
Člen | 313
+
0
-

V tom případě jsi vůbec nepochopil sílu Nette :)

Je to možné :), plno věcí neznám a rád si nechám poradit

Kdyby jsi měl všechno jako komponenty, tak ti nevadí, co se děje v presenteru.

Jakto? Vem si třeba tu zmíněnou komponentu PollControl. Dám ji na stránku (třeba profil uživatele, viz výš ten wireframe). A pokud ji zajaxovatím, tak přece nechci volat to, co je v presenteru – to mě zajímá jenom v případě klasickýho požadavku. V případě AJAXu ale už ne, protože by se vše načítalo zbytečně → a to je to, o co mi jde.

Pomocnou metodu (ajaxSendComponent) si napsat můžu, ale to neřeší ten problém, protože pokud jako komponentu do ní dosadim presenter, zase se bude volat renderXXX a tam to zase musim opodmínkovat.

Tzn., že já chci v tom signálu handleMoreComments ukončit cyklus presenteru, ale chci invalidovat snippet, abych to měl v payloadu. Ale už mě nezajímá to ostatní, co je v renderXXX, kde bude něco jako $this->template->comments = $this->comments->getAll();

smasty
Člen | 90
+
0
-

Možno by nebol až taký problém napísať si nejaký vlastný BaseAjaxPresenter, ktorý by sa staral práve o to, aby sa pri Ajaxových požiadavkach nespúštali action/render ale len tú handle metódu.

Filip Procházka
Moderator | 4668
+
0
-

Ty jsi nepochopil o co mi jde. Komponenty, když jsou v továrničkách a tvoříš je pomocí DI, tak jak jsem naznačil, vypisují data a pokládají dotazy, pouze v případě, že je vykreslíš.

Use-case

  • přijdu na stránku
    • presenter přijme request
      • v action se nic neděje
      • v render se nic neděje
      • vykresluje se šablona
        • lazy zavolání komponenty1 → dotaz na databázi
        • lazy zavolání komponenty2 → dotaz na databázi
        • lazy zavolání komponenty3 → dotaz na databázi
        • lazy zavolání komponenty4 → dotaz na databázi
    • presenter vrátí odpověď
  • pošlu ajax request
    • presenter příjme request
      • v action se nic neděje
      • identifikuje se signál, a presenter ho zkusí zpracovat
        • lazy se vytvoří komponenta, příjme signál
          • překonfiguruje se
          • změní svůj stav
          • naplní šablonu… ⇒ jeden doraz do databáze
          • zde je možnost odeslat výsledek pomocí sendResponse
      • v render se nic nedělej (možno přeskočit)
      • vykreslí se šablona (možno přeskočit)
        • zpracují se pouze požadované snippety (1 signál => 1 komponenta)
    • presenter vrátí ajaxovou odpoveď

Kde se ti co volá znovu?

Patrik Votoček
Člen | 2221
+
0
-

A co ti brání přetížit si Presenter::run a dodělat si tam to tvoje ajax[Default]?

Filip Procházka
Moderator | 4668
+
0
-

@**Patrik Votoček**: Vzhledem k tomu, že je to v kategorii feature requests, tak bych předpokládal, že chce, aby to udělal někdo jiný, za něj :)

Foowie
Člen | 269
+
0
-

@joe: Zabránit vykonání všech SQL dotazů lze předáváním odkazů do šablony (a né výsledných hodnot).
Tedy např:

presenter

public function renderXYZ() {
	$this->template->record = callback($this->model, "getRecord");
}

template

	Výsledek: {$record()}
Aurielle
Člen | 1281
+
0
-

Pak ti vyletí výjimka v půlce renderování stránky a…

Patrik Votoček
Člen | 2221
+
0
-

@HosipLan sorry to jsem nějak přehlédl…

@gmvasek přesně tak!

joe
Člen | 313
+
0
-

@Patrik Votoček: nebrání mi k tomu asi nic, nejsem v tomhle přeupravování/přetěžování zběhlý. Díky za tip.

@HosipLan: dal jsem to do této kategorie proto, protože si myslím, že by to framework mohl podporovat a ne abych všude psal podmínky (vzápětí budu komentovat tvůj use case), ne proto, že bych v tomhle vláknu čekal konkrétní odpověď na můj problém. A neznamená, že když tu nemám nálepku „Nette guru“, že si neumím nic udělat.

Mně se zdá, že jsi nějaký komponentovaný, nebudu každý výpis (chápej jeden dotaz s podporou AJAXu) psát jako novou komponentu. Komponenta se hodí tehdy, pokud ji budu používat na více místech nebo zaobaluje nějakou komplexní činnost – například košík v internetovém obchodě. Taky určitě nemáš samostatnou komponentu na přidávání zboží do košíku (to je totiž taky docela hloupost).

V tom tvém use casu si přeskakuješ ty fáze jak chceš.

v action se nic neděje
v render se nic neděje

To se právě děje, kdyby se nedělo nic, tak není žádný problém. Tím jsi napsal, že vlastně nevíš o co mi jde, se mi zdá…

Přinejmenším mám v render nastavování dat do šablony (a ne, nechci data načítat z databáze až tam).

Jinak mi chceš naznačit, že ve tvých presenterech jsou jen prázdné hlavičky

actionDetail() {}

renderDetail() {}

když se tam tedy „nic neděje“?

EDIT: nahraju někam příklad, ať je to úplně totálně jasné každému

Editoval joe (29. 6. 2011 17:10)

Foowie
Člen | 269
+
0
-

@gmvasek: … a nastane to samé jako při vyhození výjimky v komponentě (pokud není využívána v presenteru ale až makrem {control})

Filip Procházka
Moderator | 4668
+
0
-

@**Foowie**: Tohle se už řešilo. Nechce se mi hledat téma. Ale minimálně moje řešení je lepší než obyčejný callback, jehož volání v šabloně se mi vůbec nelíbí. https://gist.github.com/670938

@**joe**: Pokud chceš něco změnit, sepiš RFC. Tzn předlož problém, ukázku use-case, řešení a ukázku použití řešení.

edit:
Nevidím problém v konfigurovatelné komponentě, která mi vypisuje zboží a umí ho přidávat do košíku :)

Není úplně v pořádku, si komponenty představovat jenom jako vymazlené třídy, nebo celé balíky, které si stáhneš na addons.nette.org. Komponenta je cokoliv, co jde připojit do presenteru.

Editoval HosipLan (30. 6. 2011 8:35)

22
Člen | 1478
+
0
-

@Hospilan: ale fakt je, že například když mám komponentu formuláře, kterýmu plním setDefaults() v action, v handleru něco změním a v renderu ho pošlu jen do šablony a přitom potřebuju jen změnit/přidat selectboxu, tak se provede celej životní cyklus nebo se pletu? Na druhé straně to vlastně ani jinak nejde kvůli validaci si myslím..

Editoval 22 (30. 6. 2011 8:43)

Filip Procházka
Moderator | 4668
+
0
-

@**22**: „Celej životní cyklus“ zní strašně depresivně, jako by se to mělo narodit a umřít (což se technicky vzato i děje) :) Toho se nezbavíš, je to daň za flexibilitu MVC, ale vždycky si to můžeš přizpůsobit konkrétnímu případu, aby se nevykonávaly věci zbytečně.

@**joe**: ještě jedna věc, actionDefault a renderDefault psát nemusíš, pokud by byly prázdné :)

Editoval HosipLan (30. 6. 2011 13:10)

joe
Člen | 313
+
0
-

Tak jsem si stáhnul Nette a upravil příklad CD-collection. Pokud bych ho chtěl zAJAXovat (mazání záznamů), vypadalo by to v Presenteru asi nějak takto (github) :

Tzn. přidal bych signál handleDelete($id). Zbytek je okomentován v kódu.

„Pouhým zAJAXováním“ bych musel zasahovat do ostatních funkcí, dle mě zbytečně.

David Grudl
Nette Core | 8082
+
0
-

joe napsal(a):

„Pouhým zAJAXováním“ bych musel zasahovat do ostatních funkcí, dle mě zbytečně.

Jsou tři možnosti, jak se tomu vyhnout:

  1. AJAXem volat specializovaná view, která dělají a zobrazují jen to, co je potřeba.
  2. využívat v metodách render lazy-loading, tj. třeba $this->template->albums = $this->albums->order('artist')->order('title'); z CD-collection + konfigurovat komponenty v createComponent metodách
  3. vůbec data do šablon nevkládat, vytvořit k tomu v presenteru funkce a nechat šablony, ať si je sami získávají přes $presenter->getAlbums().
joe
Člen | 313
+
0
-

@David Grudl: Předem díky za odpověď :-)

A teď, jestli jsem to úplně správně pochopil:

AJAXem volat specializovaná view, která dělají a zobrazují jen to, co je potřeba.

To by znamenalo mít jinou adresu pro non-AJAX a AJAX požadavek, tzn. adresu bych si musel ukládat buď někam mimo v JS a nebo třeba do nějakého atributu u odkazu (třeba použít atribut data-… nebo jakýkoli jiný, nezáleží na tom). To se mi moc nelíbí :) Tím bych zaváděl normální nefunkční adresy pro neajaxové požadavky, i když by se ale nikde nepoužívaly.

konfigurovat komponenty v createComponent metodách

To právě ne vždycky jde, například pokud bych chtěl používat tu komponentu pro anketu a anketní otázku bych mohl vybírat právě v action/render fázi podle ID parametru v URL. I když možná by to šlo nějak zařídit.

vůbec data do šablon nevkládat, vytvořit k tomu v presenteru funkce a nechat šablony, ať si je sami získávají

To by asi šlo, ale pokud se nepletu, tady je zase „problém“ s případnou chybou a pak se mi nenačte celá stránka.


Osobně bych si z těchto tří asi nevybral :) a raději si tam ty podmínky, kde je potřeba, napíšu. Jen si myslím, že jsem tam měl problém ještě s něčím jiným, jen se mi to teď nedaří nějak zreprodukovat.

Filip Procházka
Moderator | 4668
+
0
-

AJAXem volat specializovaná view, která dělají a zobrazují jen to, co je potřeba.

To by znamenalo mít jinou adresu pro non-AJAX a AJAX požadavek…

public function actionDefault()
{
	if ($this->isAjax()) {
		$this->setView('ajaxDefault');
	}
}

public function renderDefault() { }
public function renderAjaxDefault() {}

Adresa se ti nezmění :)


konfigurovat komponenty v createComponent metodách

To právě ne vždycky jde, například pokud bych chtěl používat tu komponentu pro anketu a anketní otázku bych mohl vybírat právě v action/render fázi podle ID parametru v URL.

protected function createComponentPoll()
{
	// nebo si to můžeš v action uložit do privátní $this->pollId
	return new PollControl($this->context->pollsModel, $this->getParam('pollId'));
}

vůbec data do šablon nevkládat, vytvořit k tomu v presenteru funkce…

… tady je zase „problém“ s případnou chybou a pak se mi nenačte celá stránka.

To není tak úplně pravda, pokud uvažuješ, že jediné dvě věci, co se můžou pokazit, jsou,

  • že v databázi ještě nemáš žádná data (například nikdo nevložil komentář),
  • nebo se snažíš získat záznam, který neexistuje

Pak při použití dibi (a myslím že i Nette\Database) musíš mít ošetřeny syntaktické chyby v SQL, takže parse error ti nevznikne a musíš mít ošetřeny stavy, kdy záznam nenajde (prázdné/neexistující) nemůže se ti v šabloně nikdy stát chyba.

class ArticlePresenter extends BasePresenter
{
	// ...

	public function getComments()
	{
		try {
			return $this->context->commentsModel->findByArticle($this->articleId);
		} catch (ModelException $e) {
			Debugger::log($e); // zalogovat
			return array();
		}
	}

jenom v rychlosti, bez podmínek…

...
{foreach $comments = $presenter->comments as $comment}
	<div class="comment">{$comment->text}<br>Author: {$comment->authorName}</div>
{/foreach}

{if !$comments}Ještě nikdo nic nenapsal, buďte první!{/if}
...

Editoval HosipLan (2. 7. 2011 12:44)

joe
Člen | 313
+
0
-

Adresa se ti nezmění :)

To sice ne, ale to jsi mi tu napsal ještě daleko horší věc, než momentálně mám. To je právě to, čeho bych se chtěl zbavit a myslím, že by to šlo řešit nějak lépe a přehledněji. Tím zase musím přidávat if($this->isAJAX) tam, kam chci. Něco takového by bylo asi dobré přepsat v té metodě run, jak psal Patrik Votoček. Nicméně David psal možnosti, jak se tomu vyhnout a ne si to ještě ztěžovat ;-)


To je nesmysl, přece nebudu zbytečně uvádět v URL parametr, když ani nevím dopředu jaký má být. Musel bych přesměrovávat → zbytečné a pokud bych ho tam nedával, musel bych se dotazovat db → taky zbytečné.


Jo s tím máš pravdu :) Ale zdá se mi to zase nějaké zdlouhavé (rozuměj psát do modelu metodu, do presenteru metodu, …). Prostě ten jeden krok v tom presenteru (getComments) se mi zdá navíc, když prakticky to samé je v modelu.

redhead
Člen | 1313
+
0
-

To je nesmysl, přece nebudu zbytečně uvádět v URL parametr, když ani nevím dopředu jaký má být. Musel bych přesměrovávat → zbytečné a pokud bych ho tam nedával, musel bych se dotazovat db → taky zbytečné.

Co je na tom za nesmysl? Sám si uvedl, že se rozhoduješ podle parametru ID v URL a že prý to jde dělat jen v render/action fázi. HosipLan ti tu ale správně napsal, že to není pravda a že k parametru se můžeš dostat i v továrničce. Nechápu jaké „nevím dopředu jaký má být“, „musel bych přesměrovávat“ – to je nesmysl.

Filip Procházka
Moderator | 4668
+
0
-

To je nesmysl, přece nebudu zbytečně uvádět v URL parametr, když ani nevím dopředu jaký má být. Musel bych přesměrovávat → zbytečné a pokud bych ho tam nedával, musel bych se dotazovat db → taky zbytečné.

Je zřejmé, že o presenterech toho moc nevíš, protože to není nesmysl, stejně to zpracováváš v akci. Můžeš si do nějaké proměnné presenteru uložit data z akce a pak je načíst v továrničce. Pokud máš guláš v presenterech a v životním cyklu aplikace, tak se ti nedivím, že jsou ti podmínky přítěží.

Zjisti si prosím, jak fungují persistentní parametry a taky si uvědom, že v presenteru si můžu definovat vlastnosti, jako v jakékoliv jiné třídě. Je to totiž (trošku vyžranější) třída.

/** @var MyApp\Profile */
private $profile;

/** @persistent */
public $profileId;

public function actionDefault($profileId)
{
	$this->profile = $this->context->profileModel->find($profileId);
}


protected function createComponentPoll()
{
	return new PollControl($this->context->pollModel, $this->profile->pollId);
}

Kde se ti co přesměrovává? Kde máš co v url?


Jo s tím máš pravdu :) Ale zdá se mi to zase nějaké zdlouhavé (rozuměj psát do modelu metodu, do presenteru metodu, …). Prostě ten jeden krok v tom presenteru (getComments) se mi zdá navíc, když prakticky to samé je v modelu.

Komu není rady, … :)

Editoval HosipLan (2. 7. 2011 19:59)

joe
Člen | 313
+
0
-

@redhead:
Nesmysl proto, protože v URL mám například ID topicu a ne konkrétní ID anktety, proto ho nemůžu volat $this->getParam('pollId');

@HosipLan:
O Presenterech toho možná nevím co ty, ale vím, že bych to mohl udělat jak jsi poslal teď (nikoli předtím, k čemu jsem se vyjadřoval). Takže otázky „Kde se ti co přesměrovává? Kde máš co v url?“ jsou tady celkem opožděné :)

Ano, je fajn vědět, že Presenter je třída jako každá jiná :)

Uložit si to do různých atributů třídy samozřejmě můžu, ale proč bych to dělal? Jen kvůli tomu, aby se to zpracovalo později? To mi nedává moc smysl… Pořád mi to přijde jako vyhýbání se nějakému komplexnímu řešení, které by mi přišlo přehlednější.

Při prvním kouknutí do kódu by ti bylo hned jasné, proč to je přes atribut třídy a není to nastaveno hned v té action/render té komponentě?

$this['pollControl']-> ... ;
Filip Procházka
Moderator | 4668
+
0
-

Už vím co máš za problém. Nevoní ti Inversion of Control :)

O Presenterech toho možná nevím co ty, ale vím, že bych to mohl udělat jak jsi poslal teď (nikoli předtím, k čemu jsem se vyjadřoval). Takže otázky „Kde se ti co přesměrovává? Kde máš co v url?“ jsou tady celkem opožděné :)

Vskutku, ale to je přirozený vývoj diskuze :) Předpokládal jsem, že takovéto základní věci znáš, když jsi psal, abych tě nepodceňoval.

Uložit si to do různých atributů třídy samozřejmě můžu, ale proč bych to dělal? Jen kvůli tomu, aby se to zpracovalo později? To mi nedává moc smysl… Pořád mi to přijde jako vyhýbání se nějakému komplexnímu řešení, které by mi přišlo přehlednější.

  1. já se problému nevyhýbám, poskytuju ti řešení (alespoň dočasné), které je funkční a pevně věřím, že správné
  2. a proč ti to nedává smysl? protože máš filosofické problémy to použít, není na tom vůbec nic špatného. Ba naopak, říká se tomu lazy inicializace, Inversion of Control, nebo taky konrétněji Dependency Injection, …
  3. sepiš RFC (problém, důsledky, řešení, důsledky řešení) do příslušné sekce fóra, pokud máš nápad jak to vyřešit. Ale dej si záležet, napsat pár komentářů do kódu stačit nebude

Při prvním kouknutí do kódu by ti bylo hned jasné, proč to je přes atribut třídy a není to nastaveno hned v té action/render té komponentě?

$this['pollControl']-> ... ;

Samozřejmě by mi to bylo jasné, protože vím,

  • že když komponentu zavolám v akci, tak se ochuzuju o lazy vytvoření té komponenty, což je celý princip továrniček,
  • že si můžu vyhledat lokální použití proměnné, když si ji ukládám do property presenteru, tak bude nejspíš ještě někde použita. Když si ji ukládám v akci, tak bude v handleru, v komponentě, nebo v render ⇒ kouknu tam
  • mažeš snad automaticky z tříd vlastnosti, pokud na první pohled nevíš, kde jsou použity? To je totiž jediný důvod, který mě napadá, proč by ti něco takového v třídě mohlo vadit. Ale to pak toho člověk moc nenapíše :)
  • a protože používám Dependency Injection, které jsme tak opěvovali a vynutili si krásný nový DI Container :)

Jsem zvědav, jestli se nad tím třeba i zamyslíš a řekneš mi co ti vadí na private $pollId; v presenteru, nebo to jen budeš odmítat, s tím, že ti to nedává smysl :) Což je, s prominutím, dost zabedněné uvažování.