Cache routeru – nedaří se v cache uchovat routy
- Blizzy
- Člen | 149
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
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
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)
- Blizzy
- Člen | 149
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
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)
- David Grudl
- Nette Core | 8218
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
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)