2009-09-02 21 views
1

我在與Zend_Navigation的頁面層次結構麻煩,當我緩存它使用Zend_Cache是​​越來越混亂。Zend_Navigation緩存

背景:我有大約50頁,約300種產品存儲在數據庫中。我查詢數據庫並創建一個數組來提供給Zend_Navigation。

緩存是

 $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/') 
          ); 

這工作得很好

$struct = $cache->load('Zend_Navigation'); 
    if (empty($struct)) 
    { 
     $cache->save($struct = self::getSiteStructure()); 
    } 
    return new Zend_Navigation($struct); 

這被擾亂如果不從緩存中拉

$struct = $cache->load('Zend_Navigation'); 
    if (empty($struct)) 
    { 
     $cache->save($struct = new Zend_Navigation(self::getSiteStructure()); 
    } 
    return $struct; 

導航工作正常。是的,顯而易見的解決方案是不緩存Zend_Navigation,但構造函數做了很多工作來構建其內部表示:有意義的做緩存與儘可能多的預先計算,因爲我可以...

我'米仍然試圖查看是否有一個模式的混亂結果。樹中沒有循環/循環。

回答

1

閱讀這個問題後,我參加了一個快速瀏覽一下Zend_Navigation代碼,它似乎不應該有與使用序列緩存任何固有的問題。然而,看着Zend_Navigation文檔,我發現以下內容:

toArray()方法將容器及其中的頁面轉換爲數組。這對於序列化和調試很有用。 - Zend Navigation Containers: Other

您可能希望創建Zend_Navigation對象,請使用指定者()函數創建數組和緩存這一點。重新創建數組中的頁面應該相當便宜,儘管您可能想要進行一些測試。

另外,如果可能的話,文件與Zend框架維護一個bug報告,以便他們可以看看它。

Zend_Navigation雖然一個有趣的組成部分,可以說是一個有用的是不是我用的多。對於在內存中擁有超過10,000個對象的大型網站來說,這不是一個聰明的想法,某些項目在Zend_Navigation中的實現方式使其變得緩慢且笨拙。許多使用Zend Framework的開發人員已經找到了實現相同目標的其他方法。

+0

感謝。發現。查看代碼,他們使用spl_object_hash()http://nz.php.net/manual/en/function.spl-object-hash.php來計算容器內頁面的散列鍵。在反序列化()時顯然會搞砸了。 所以答案是使用toArray()。但是如果您從Bootstrap緩存,則會出現更多問題。答案似乎是創建一個控制器動作助手並按需加載它。 – Steve 2009-10-06 07:16:58

0

感謝您的帖子;我認爲有可能是結合Zend_Navigation和Zend_Cache是​​問題,但我已經能夠使用保存方法的正常Zend_Navigation對象,然後檢索對象從緩存中回沒有任何需要使用指定者()

X-Istence:我同意,隨着導航對象的大小增長,它可能變得相當笨拙;儘管我將不得不在代碼中深入挖掘以完成對尺寸臨界點的理解。

+1

我的經驗是,它只適用於小於200頁的小網站。我將它用於中等規模的電子商務網站(400個產品+ 100頁的頁面),感覺它的吱吱聲有點 - 除非我做錯了,當然... – Steve 2011-05-09 23:05:47

1

只是一個有關緩存頁面陣列警告...

如果您緩存來自toArray()的數組,並且想要簡單地使用setPages($pagesFromCache),則需要停用緩存陣列中的所有頁面以備將來使用。

小心,Zend_Navigation_Page_Mvc::isActive()檢查當前請求。這意味着即使您撥打setActive(false),您當前的MVC頁面isActive()仍然會返回true

我發現停用所有頁面的唯一方法是遞歸走線槽結果數組:

$pages = $navigation->toArray(); 

array_walk_recursive(
    $pages, 
    function(&$item, $key) 
    { 
     if($key === 'active') 
      $item = false; 
    } 
); 

$cache->save($pages, 'pages');