Cachování v šablonách – jak na to?

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

Krásný den,

mám presenter který vytvoří stránku, výsledný obsah je v podstatě statický a je ho jen třeba jednou za cca 15 minut obnovit.

Chtěl jsem použít cache v šabloně, dle dokumentace se domnívám že by mělo stačit jen obalit šablonu do tagu cache:

{cache $type, expire => '15 minutes'}
  {block content}
    ... nějaký obsah ...
  {/block}
  {block head}
    <style>...</style>
   {/block}
{/cache}

Takto nasazeno to ale nehlásí žádnou chybu, obsah se evidentně neukládá do cache, v /temp/cache se žádný soubor nevytvořil.

můžete mě prosím někdo nasměřovat, co je ještě potřeba udělat proto, aby cache v šabloně fungovala ?

S pozdravem Honza Vrána

David Matějka
Moderator | 6445
+
0
-

obaluj cache makrem az vnitrek tech bloku

vraja
Člen | 6
+
+1
-

Díky za pomoc, pomohlo to. :)

Nicméně to asi nefunguje tak jak jsem si představoval.

Funkce renderDefault se spustí, provede se „drahé“ načtení externích dat, ale nakonec se vypíše stránka z cache.

Takže asi tedy musím provést nacachování těch dat již v modelu ?

Honza Vrána

greeny
Člen | 405
+
0
-

Cachuj data tam kde se získávají:

  • pokud jsou data výsledek nějaké model funkce, cachuj to přímo v té funkci
  • pokud jsou data složitě generovaný HTML (nebo jiný) výstup, cachuj to v šabloně

Do presenteru IMHO cache nepatří, ale taky se tam dá použít

Zax
Člen | 370
+
0
-

@vraja Nespouštěj tu drahou metodu v renderu, ale místo toho si předej do šablony anonymní funkci, která tu drahou metodu spustí až když bude potřeba:
$this->template->data = function() {return $this->expensiveMethod();};

{cache}
{$data()}
{/cache}

Nyní se drahá metoda spustí jen poprvé a pak už se vrací jen HTML z cache a k volání se to nedostane.

newPOPE
Člen | 648
+
0
-

Alebo este mas moznost pustit metodu na Presenteri v sablone (pride mi to prehladnejsie ako @Zax ovo riesenie).

	{cache}
	{$presenter->foo()}
	{/cache}
greeny
Člen | 405
+
0
-

A nebo (čti nejlépe) v té „drahé metodě“ místo těch dat budeš pracovat s cachí. Cachování v šabloně je hlavně kvůli generovaní složitého zdrojáku (RSS feedy, sitemap, apod)

Příklad.:

class Model
{
	/** @var Cache */
	private $cache;

	public function __construct(IStorage $storage)
	{
		$this->cache = new Cache($storage);
	}

	public function getData()
	{
		return $this->cache->load('data', function (&$dependencies) {
			return $this->getDataFromDb(); // náročná operace
		});
	}
}
Jan Mikeš
Člen | 771
+
0
-

@newPOPE šahání ze šablony na funkce presenteru mi nepříjde úplně čisté

@vraja takto nějak může vypadat použití cache mimo presenter a šablonu (imho je to mnohem čistější řešení, oddělís tím logiku od předávání do šablony a od samotné šablony):

//config.neon
services:
	- MyService(@cacheStorage)

// MyService.php
class MyService {
	private $cache;

	public function __construct($storage)
	{
		$this->cache = new Nette\Caching\Cache($storage, "MyCustomNamespace");
	}


	public function getResult($xyz)
	{
		return $this->cache->load("result-$xyz", function([Nette\Caching\Cache::EXPIRE => '20 minutes']) use($xyz) {
			return $this->myExpensiveFunction($xyz);
		});

		/* lze napsat i takto: */
		$data = $this->cache->load("result-$xyz");

		if ($data === NULL) {
			$data = $this->cache->save("result-$xyz", $this->myExpensiveFunction($xyz), [Nette\Caching\Cache::EXPIRE => '20 minutes'])
		}

		return $data;
	}


	public function myExpensiveFunction($xyz)
	{
		// Random logika
	}


	// Presenter.php
	public function renderDefault()
	{
		$this->template->data = $this->myService->getResult($abcd);
	}

	// template.latte
	{$data}

Kod jsem netestoval, ale ± by to melo sedet :-) jde spise o to ukazat, jak lze cache vyuzivat

edit: @greeny to stihl napsat rychleji :-)

Editoval Lexi (11. 1. 2016 15:18)

vraja
Člen | 6
+
0
-

Krásný den,

Děkuji všem za rady, nakonec my přišlo nejelegantnější použít variantu se službou tak jak ji to tu nastřelil LEXI.

Chápu, že by se data měla cachovat tam kde vznikají, takže v modelu kde je potřeba načíst data, aby všechny volání modelu tyto data mohla použít.

Nicméně chtěl jsme výsledek maximálně nacachovat, aby se při zobrazení provádělo co nejméně kódu.

Aplikace v modelu načítá rssfeed, v prezenteru se ten feed zamíchá a ořízne na tři záznamy, v šabloně se tyto tři záznamy zobrazí.

Protože zobrazování výsledku se děje mockrát a i to míchání není potřeba provádět často, tak mi přišlo nejvhodnější uložit výsledek, a ten jen občas obnovit.

Čily stav, kdy přijdu na stránku, zjistím zda je vysledek v cache a pokud je tak se zobrazí, když ne tak se výsledek vygeneruje.

Protože dle mého názoru se první spouští kód prezenteru, pak by cache asi patřila právě do něj.

S pozdravem Honza Vrána