2010-04-27 130 views
1

我有一個數據庫,其中包含按類別和子類別組織的產品。問題是我通過查詢分類表來生成一個菜單。因爲類別幾乎相同(他們可以每個月更改/添加一次),所以我不認爲每次訪問網頁都必須查詢數據庫。你對我有更好的想法嗎?從菜單生成的PHP菜單

非常感謝!

ps:我正在使用CakePHP框架,但您的答案/想法不必與它相關。我只是找到memcache

回答

2

我認爲在這個例子中,我會結合使用動作緩存和視圖緩存。我不會深究不同的緩存引擎,只是解決您的問題的基礎知識。

您需要做的第一件事就是開啓緩存。在app/config/core.php中,您需要進行一些更改。首先,註釋掉Cache.disable行:

//Configure::write('Cache.disable', true); 

二,取消對Cache.check行:

Configure::write('Cache.check', true); 

最後,你需要做CacheHelper提供給所有的意見,所以將它添加到$helpers成員定義在app/app_controller.php

class AppController extends Controller 
{ 
    var $helpers = array('Cache'); 
} 

接下來,我們將設置包含您的貓的視圖元素egory菜單(在控制器的東西看起來有點後退之前做視圖的東西,但忍受我 - 它會有意義的)。將菜單放在視圖元素中會緩存起來要比試圖有選擇地將較大視圖或佈局的某些部分指定爲未標記爲<cake:no-cache></cake:no-cache>標記更簡單一些。

下面是一個示例視圖元素,呈現在一個簡單的無序列表類別菜單(<ul>):

<?php 
    $menuItems = $this->requestAction(array('controller'=>'categories','action'=>'menu')); 

    echo $html->nestedList($menuItems, 'ul'); 
?> 

您可能已經由一個或更多的人告訴記者,在過去的這requestAction是邪惡的,因爲它啓動一個全新的調度。這是真的。你應該避免requestAction像瘟疫,,除了當你正在做這種類型的視圖緩存,在這種情況下,這是最好的辦法。

我們將此新視圖元素存儲爲app/views/elements/category_menu.ctprequestAction調用CategoriesController中的menu操作。下面是CategoriesController樣子,然後我會去通過一點一滴:

class CategoriesController extends AppController 
{ 
    var $cacheAction = array(
     'menu/' => '1 day' 
    ); 

    function menu() 
    { 
     return $this->Category->find('list', array(
      'fields' => array('Category.id','Category.label'), 
      'order' => array('Category.order') 
     )); 
    } 
} 

這裏做的事情:

  • $cacheAction成員定義告訴蛋糕,它應該緩存menu結果行動1天。
  • menu方法返回一個一維數組的類別,使用Category.id作爲鍵,Category.label作爲值。

所以,讓我們回過頭看看到目前爲止。我們有一個category_menu元素,它請求CategoriesController::menu操作。當收到這個請求時,Cake會檢查這個動作的結果是否被緩存,並且沒有過期。如果緩存的結果仍然有效,Cake會返回它,而不會調用我們定義的menu方法。否則,Cake將調用該方法,並將緩存結果。視圖元素然後將結果呈現爲一個nestedList。

然後,剩下的就是在其他視圖中使用視圖元素。這裏有一個簡單的示例app/views/layouts/default.ctp

<html> 
[ snip... ] 
<body> 
<div class="category-menu"> 
    <?php echo $this->element('category_menu', array('cache'=>'1 day')); ?> 
</div> 
<div class="content"> 
    <p>Lorem ipsum sit dolor amet.</p> 
</div> 
</body 
</html> 

我們使用熟悉的View::element來渲染我們前面創建的category_menu視圖元素,但我們也知道,我們想要再渲染視圖元素蛋糕,然後緩存此渲染過的版本,並堅持一個月。對該元素的任何後續請求,直到一個月過去或我們清除緩存,都會傳遞預渲染的視圖元素。它甚至不會解釋app/views/elements/category_menu.ctp,更不用說調用requestAction,或者命中數據庫。

爲確保您對Category所做的更改充滿體現,您可以在創建/更新操作中調用全局功能clearCache()。關於clearCache()的一個警告:這是一個霰彈槍的方法:不雅但有效。 clearCache()清除整個緩存,而不是有選擇地只清除必要的視圖。然而,這是一種簡單的方法,並且考慮到您每月更新類別,必須每月重新生成一次緩存,這可能值得減少選擇性方法的麻煩。

很長的答案! HTH

1

你可以寫一個腳本來查詢可用類別的數據庫,並將輸出寫入到PHP文件,/inc/categories.php,這是使用你的網站。

這個腳本是不是由cron作業每月一次多次跑或請你

+0

如果你這樣做了,只要有人改變類別就可以運行更新腳本。 – Twelve47 2010-04-27 11:21:47

+0

這不是一個非常Cake-y的解決方案。 – 2010-04-27 14:56:28

1

馬克的回答是正確的,我喜歡它的簡單。僅僅因爲它不是Cakey並不意味着你應該使用它。我已經讓自己更加悲傷,並且時間試圖將某些東西變成一種「cakey」格式,而不是我所願意承認的。

在快速發展中,有時候需要黑客入侵。

這就是說,如果你想走更多像路線的蛋糕,我建議你查看查詢緩存。關於它的好文章是http://www.endyourif.com/caching-queries-in-cakephp/