Reputation: 3649
I'm having trouble with the page hierarchy of Zend_Navigation getting scrambled when I cache it using Zend_Cache.
Background: I have approx 50 pages and approx 300 products stored in a database. I query the database and create an array to feed to Zend_Navigation.
The cache is
$secondsBetweenRefreshes = APPLICATION_ENV == 'development' ? 30 : 300;
self::$cache = Zend_Cache::factory( 'Core', 'File',
array( 'automatic_serialization' => true,
'lifetime' => $secondsBetweenRefreshes ),
array( 'cache_dir' => CACHE_PATH . 'nav/' )
);
This works fine
$struct = $cache->load('Zend_Navigation');
if (empty($struct))
{
$cache->save($struct = self::getSiteStructure() );
}
return new Zend_Navigation( $struct );
And this gets scrambled
$struct = $cache->load('Zend_Navigation');
if (empty($struct))
{
$cache->save($struct = new Zend_Navigation( self::getSiteStructure() );
}
return $struct;
The navigation works fine if it is not pulled from the cache. Yes, the obvious solution is not to cache the Zend_Navigation, but the constructor does a lot of work to build its internal representation: makes sense to do the caching with as much pre-computed as I can...
I'm still trying to see if there is a pattern in the scrambled results. There are no loops / cycles in the tree.
Upvotes: 1
Views: 1851
Reputation: 3023
Just a warning about caching pages array...
If you cache the array from toArray()
, and want to simply use setPages($pagesFromCache)
, you need to deactive all pages in cached array for future use.
Be careful, Zend_Navigation_Page_Mvc::isActive()
checks current request. It means isActive()
of your current MVC page still return true, even if you called setActive(false)
.
The only way I found to deactivate all pages is to recursively walk trough the resulting array :
$pages = $navigation->toArray();
array_walk_recursive(
$pages,
function(&$item, $key)
{
if($key === 'active')
$item = false;
}
);
$cache->save($pages, 'pages');
Upvotes: 1
Reputation: 1
Thanks for the post; I thought there may be issues combining Zend_Navigation and Zend_Cache, but I've been able to use the save method on a normal Zend_Navigation object and then retrieve the object back from the cache without any need to use toArray().
X-Istence: I agree that as the size of the navigation objects grow, it may become become rather unwieldly; though I'll have to dig deeper in the code to complete my understanding as to the size tipping point.
Upvotes: 0
Reputation: 16665
After reading this question, I took a quick glance at the Zend_Navigation
code and it does not seem that there should be any inherent issues with caching it using serialisation. However looking at the Zend_Navigation documentation I found the following:
The toArray() method converts the container and the pages in it to an array. This can be useful for serializing and debugging. - Zend Navigation Containers: Other
You may want to create the Zend_Navigation object, use the toArray() function to create the array and cache that. Re-creating the pages from an array should be fairly inexpensive, although you may want to do some testing.
Also, if possible, file a bug report with the Zend Framework maintainers so that they can take a look at it.
Zend_Navigation
although an interesting component, and arguably a useful one is not something I use much. For big websites having 10,000+ objects in memory is not a smart idea, and the way certain items are implemented in Zend_Navigation
makes it slow and unwieldy. Many developers using the Zend Framework have found other ways of accomplishing the same goals.
Upvotes: 1