Drupal API: drupal_render_cache_by_query [基於 DB Query,緩存你的查詢結果]

论坛: 

在網站中,經常有一些資料是相同的,並不必要每一次刷新都重建,若果這在一個大的 DB 資料庫,或一個複雜的 SQL 查詢中,很消耗資源。將查詢結果進行緩存是一個極好的解決方法。

Drupal 7 新增了 API drupal_render_cache_by_query() 來嘗試解決以上問題,主要用作緩存相同的 DB Query 的結果,為 DB Server 減輕查詢負擔。也就是說,當 DB Query 有改變,這會重新產生,否則這會直接由 DB 取得預早的緩存結果。

在 Drupal Core 中也只有在 Forum Block 中使用過一次。由於太新了,這唯一的一次實例也出錯了,以下是修正的版本示範:

function forum_block_view($delta = '') {
$query = db_select('forum_index', 'f')
->fields('f')
->addTag('node_access');
switch ($delta) {
case 'active':
$title = t('Active forum topics');
$query
->orderBy('f.last_comment_timestamp', 'DESC')
->range(0, variable_get('forum_block_num_active', '5'));
break;

case 'new':
$title = t('New forum topics');
$query
->orderBy('f.created', 'DESC')
->range(0, variable_get('forum_block_num_new', '5'));
break;
}

$block['subject'] = $title;
// Cache based on the altered query. Enables us to cache with node access enabled.
$block['content'] = drupal_render_cache_by_query($query, 'forum_block_view', CACHE_TEMPORARY, DRUPAL_CACHE_PER_ROLE);
$block['content']['#access'] = user_access('access content');
return $block;
}

上面,我們很清楚可見:

$query - db_select() Object (沒有執行 $query->execute())
forum_block_view - 這是一個 callback,將會呼叫 forum_block_view_pre_render 進行後續處理,並將處理好的數據作為緩存資料
CACHE_TEMPORARY - 緩存的時間性設定,可參考 cache_set() $expire
DRUPAL_CACHE_PER_ROLE - 這項是緩存的方式,比如:
DRUPAL_CACHE_PER_ROLE (以角色區分)
DRUPAL_CACHE_PER_PAGE (以每一頁面區分)。
也可以兩者同時區分:"DRUPAL_CACHE_PER_PAGE | DRUPAL_CACHE_PER_ROLE" (既以頁面又以角色區分)。
還有一個是 DRUPAL_CACHE_PER_USER。選擇那一個要按實際需求,過份濫用也有可能會造成 DB 壓力。