Cache routeru – nedaří se v cache uchovat routy

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

Už dlouho se pokouším o cache routeru a stále se mi to nedaří, prosím o pomoc.

Tady je testovací kód, který nefunguje, mám připravený router, při zápisu do cache vše funguje, jakmile ale zkusím znovu otevřít cache, je tam router, ale bez rout.

$router je instance MultiRouter a je naplněná routami. Nastavím namespace, uložím do cache, routy ještě jsou uložené, pak znovu nastavím namespace (to by se udělalo při dalším spuštění aplikace) a routy už tam nejsou, jen router.

		$this->cache = Environment::getCache('Application');
		$this->cache->save('router', $router);

		// výpis routeru a jeho rout poprvé (v tomto případě se routy vypíšou)
		Debug::barDump($this->cache['router'], 'Router v cache pred');
		foreach ($this->cache['router'] as $route) Debug::barDump($route);

		$this->cache = Environment::getCache('Application');

		// výpis routeru a jeho rout podruhé (teď už se vypíše jen router, ale žádné routy)
		Debug::barDump($this->cache['router'], 'Router v cache po');
		foreach ($this->cache['router'] as $route) Debug::barDump($route);

Nemůžu přijít na to, kde dělám chybu, prosím poraďte.

Filip Procházka
Moderator | 4668
+
0
-

A co takhle?

Class MyApplication
{

	protected $cache;


	public function __construct()
	{
		$this->cache = Environment::getCache('Application');
	}


        protected function setupRouter()
        {

		if( Environment::isProduction() AND isset($this->cache['router']) ){
			$this->setRouter($this->cache['router']);

		} else {
			$router = $this->getRouter();

			// Modules routes
			foreach( $this->modules AS $module ){
				$module->setupRouter($router);
			}

			// Homepage
			$router[] = new SiteRoute('<? (index\.(php|html?))? >', array(
				'presenter' => 'Default',
				'action' => 'default',
			), Route::ONE_WAY);

			$this->cache->save('router', $router);
		}
        }

}
class BlaBlaModule extends BaseModule
{

        public function setupRouter(IRouter $router)
        {
		$router[] = new Route('/blabla/<presenter>/<action>/<id>', array(
			'module' => 'BlaBla',
			'presenter' => 'Default',
			'action' => 'default',
			'id' => Null,
		));
        }

Editoval HosipLan (6. 7. 2010 20:08)

Blizzy
Člen | 149
+
0
-

Zřejmě se jedná o bug

Izoloval jsem kód, který nefunguje: https://gist.github.com/465745

Nejdůležitější část zkopíruju přímo sem:

$cache = Environment::getCache('NamespaceTest');
$httpRequest = Environment::getHttpRequest();

$noCachedRouter = new Nette\Application\MultiRouter;
$noCachedRouter[] = new Route('', array(
	'presenter' => 'Abc',
	'action' => 'Def',
), Route::ONE_WAY);

if (isset($cache['router'])) {
	$cachedRouter = $cache['router'];

	if ($cachedRouter->match($httpRequest) != $noCachedRouter->match($httpRequest)) {
		dump('Router z cache nezpracuje http request stejne jako necachovany router');
	} else {
		dump('Cachovany router funguje stejne jako bez cache.');
	}
} else {
	dump('Do cache byl ulozen router, obnovte (F5).');
	$cache->save('router', $noCachedRouter);
}

Zjistil jsem, že na stabilní 0.95 kód funguje, na 1.0 nefunguje. Tím, že funguje myslím, že router z cache matchuje HTTP požadavek na "" (prázdný řetězec) stejně jako necachovaný router.

Konkrétně ve verzi 1.0 napíše:

Warning: Invalid argument supplied for foreach() in Nette\Application\Routers\MultiRouter.php on line 49

Na ř. 49 se prochází foreachem routy v MultiRouter a ty se zřejmě při ukládání/načítání z cache ztratí, tím pádem ten MultiRouter z cache nezpracuje httpRequest stejně jako obyčejný router.

Všechno způsobil pravděpodobně tento commit, který změnil MultiRouter, kvůli odstranění závislosti na Nette\Collections\ArrayList.

Editoval Blizzy (6. 7. 2010 21:33)

LM
Člen | 206
+
0
-

Tohle je bug v SplQueue, nejde serializovat http://bugs.php.net/bug.php?….

Blizzy
Člen | 149
+
0
-

LM napsal(a):

Tohle je bug v SplQueue, nejde serializovat http://bugs.php.net/bug.php?….

Tím se vše vysvětluje, díky. Když SplQueue nejde serializovat, MultiRouter by jej asi neměl používat.

jansfabik
Člen | 193
+
0
-

Blizzy napsal(a):

LM napsal(a):

Tohle je bug v SplQueue, nejde serializovat http://bugs.php.net/bug.php?….

Tím se vše vysvětluje, díky. Když SplQueue nejde serializovat, MultiRouter by jej asi neměl používat.

řešení vidím v tom, že MultiRouter v magické metodě __sleep převede SplQueue na pole a v metodě __wakeup by zase pole převedl na SplQueue

Editoval jansfabik (7. 7. 2010 18:57)

Blizzy
Člen | 149
+
0
-

jansfabik napsal(a):

řešení vidím v tom, že MultiRouter v magické metodě __sleep převede SplQueue na pole a v metodě __wakeup by zase pole převedl na SplQueue

Díky, to mě nakoplo, nakonec jsem ve svém routeru implementoval rozhraní \Serializable.

David Grudl
Nette Core | 8218
+
0
-

To jsou holomci, jak jsem jen mohl očekávat, že nové SPL třídy budou bez problémů… Ok, přepisuju SqlQueue na ArrayList.

arron
Člen | 464
+
0
-

David Grudl napsal(a):

Ok, přepisuju SqlQueue na ArrayList.

Nejsem si jisty jestli to pomohlo:

$cache = Environment::getCache('Application');
$router = $this->getRouter();

if (isset($cache['applicationRoutes'])) {
    $router = $this->cache['applicationRoutes'];
    //v promene $router je to, co bysme cekali
    print_r($router);
    //nicmene tady uz je jenom multirouter ber rout
    print_r($this->getRouter());
} else {
    $router[] = new Route('index.php', array(
        'presenter' => 'Homepage',
        'action' => 'default',
    ), Route::ONE_WAY);

    $router[] = new Route('<presenter>/<action>', array(
        'presenter' => 'Homepage',
        'action' => 'default',
    ));
    $this->cache->save('applicationRoutes', $router, array(\Nette\Caching\Cache::TAGS => array('routes')));
    //data jsou v cache ulozena v poradku
}

Nette Framework 1.0-dev (revision 70f3e59 released on 2010–09–02)

Editoval arron (9. 9. 2010 1:11)

David Grudl
Nette Core | 8218
+
0
-

Vždyť tu proměnnou $router přepisuješ jiným obsahem.

arron
Člen | 464
+
0
-

Ha, uz to vidim. Spatne jsem to pochopil…omluva:-) (jsem ja to ale k*kot ;-))