Pořadí spouštění metod presenteru: Shutdown vs Render šablony
- josef.sabl
- Člen | 153
Ahoj, podle tohoto obrázku bych si myslel, že:
- Proběhne vyrenderování šablony
- Spustí se metoda presenter->shutdown()
Ale není tomu tak. Možná proběhne kompilace šablony, ale určitě ne její spuštění (vyrenderování). Mám takovýto kód:
class MyPresenter extends BasePresenter
{
public function shutdown($response)
{
parent::shutdown($response);
echo "shutdown";
}
public function callMeFromTemplate()
{
echo "template";
}
}
A k tomu šablonku:
{block content}
{$presenter->callMeFromTemplate()}
No a oproti mojemu očekávání je ve výstupu nejdříve „shutdown“ a potom teprve „template“. Myslel jsem si, že hraje roli nějaké zachytávání výstupu v šabloně a jeho vypsání až na konci, ale i když obě echa v debuggeru označím breakpointem, nejdříve se provede ten v shutdown a teprv pak až ten ze šablony?
O co se tedy snažím:
V šabloně vypisuju nějaké propertky modelu, které se lazy způsobem
inicializují. Tzn. např $object->lastDisplayed obsahuje nějaké datum, kdy
byl objekt naposledy vykreslený a tato metoda dělá něco takového:
$this->lastDisplayed = Date(); $this->persist(); return $this->lastDisplayed
.
Používám Doctrine a v průběhu běhu skriptu persistuju objekty na úrovni Doctrine a až na konci jedinkrát zavolám $documentManager->flush(), což zapíše všechny změny do databáze. A toto mám právě v presenter->shutdown. Datum se v šabloně správně zobrazí, do databáze se nezapíšou, páč se $object->getLastDisplayed() ještě nespustilo a pořadí spuštění kódu je tedy:
$documentManager->flush();
$object->lastDisplayed = Date();
$documentManager->persist($object);
Stručně řečeno potřebuji spustit nějaký kód na konci běhu skriptu, kdy už je celá šablona vykreslená. Takže:
$object->lastDisplayed = Date();
$documentManager->persist($object);
$documentManager->flush();
Co dělám špatně? Jak to udělat lépe? Pomohlo umístění $documentManager->flush() na konec www/index.php, ale mi přijde dost nepěkné.
Díky :-)
Editoval josef.sabl (30. 5. 2016 17:29)
- jiri.pudil
- Nette Blogger | 1032
V první řadě bych tam hledal problém v návrhu: šablona je od toho,
aby věci vykreslila, ne aby měnila vnitřní stav entit. Ten lastDisplayed
můžeš aktualizovat třeba zrovna v render*
metodě. Pokud není
možné zasáhnout do tohohle, aspoň trošičku méně nepěkné řešení je
navěsit to na Application::$onShutdown
.
- josef.sabl
- Člen | 153
jiri.pudil napsal(a):
V první řadě bych tam hledal problém v návrhu: šablona je od toho, aby věci vykreslila, ne aby měnila vnitřní stav entit. Ten lastDisplayed můžeš aktualizovat třeba zrovna v
render*
metodě. Pokud není možné zasáhnout do tohohle, aspoň trošičku méně nepěkné řešení je navěsit to naApplication::$onShutdown
.
Hmm, Application::$onShutdown jsem přehlídl, zkoušel jsem Presenter::$onShutdown a ten se taky spouští brzy. Díky.
K té výtce k návrhu:
Jasně, tušil jsem, že součástí odpovědi bude něco takového :)
Je to složitější a hraje tam roli několik věcí: MongoDB, Doctrine, Cachování v šablonách, Lazy loading a inicializace objektů a cílem tohohle návrhu je maximální optimalizace počtu dotazů do databáze a taky celková velikost databáze.
Představ si aplikaci, která pracuje s obrovským množstvím objektů, které mají velké množství properties, které mají náhodnou povahu a v praxi se jich většina nevyužije. Je možné je tedy inicializovat a do databáze uložit až v okamžiku, kdy se na ně uživatel poprvé podívá v UI.
Ale co se týká podstaty dotazu, tak tam jde pouze o to: Jak spustit kód až úplně na konci běhu aplikace. Ten můj use case byl jen pro ilustraci :)
Editoval josef.sabl (1. 6. 2016 15:18)