之前我寫了一篇在 Laravel 4 框架中使用阿里云 OCS 緩存的文章,介紹了如何通過擴展 Laravel 4 來支持需要 SASL 認證的阿里云 OCS 緩存服務。有網友問我,ACE 的緩存怎么在 Laravel 4 中使用。我本來覺得應該可以完全用相同的辦法,后來自己嘗試的時候才發現,ACE 的緩存差別非常大。所以再寫一篇,介紹一下如何在 Laravel 框架中使用阿里云 ACE 的緩存服務。
如何擴展 Laravel 的緩存驅動
在 Laravel 4 中使用 Cache::get($key), Cache::put($key, $value, $minutes) 這樣的代碼時,實際上是訪問 實例化的 Illuminate/Cache/Repository, 所以我們通過 Cache::extend 方法擴展自定義緩存驅動時,同樣應該返回一個 Illuminate/Cache/Repository 對象。
Laravel 4 內置的 Memcached 緩存驅動,實現的流程是這樣的:
1.創建一個標準 Memcached 類的新對象
2.用上一步創建的 Memcached 對象創建一個實現了 Illuminate/Cache/StoreInterface 接口的 Illuminate/Cache/MemecachedStore 對象。
3.用上一步創建的 MemcachedStore 對象創建一個 Illuminate/Cache/Repository 對象。
所以我們在擴展自定義的 Cache 驅動時,根據自己的情況,選擇上面的某一個步驟自定義,最終還是要返回 Illuminate/Cache/Repository 對象。比如上一篇文章中,我就是在第一步,創建標準 Memcached 對象之后,通過 setSaslAuthData() 方法設定 OCS 需要的用戶名密碼。之后第2步、第3步并不需要自定義。
ACE 的緩存服務
阿里云 ACE 的緩存服務,跟默認的 OCS 有所不同:
1.通過 Alibaba::Cache() 方法獲得 Cache 對象。
2.ACE 的 Cache 對象與標準 Memcached 對象不同,支持的方法有限。
所以,這次第一步得到的不是標準 Memcached 對象,因此就不能創建 Illuminate/Cache/MemcachedStore 對象。需要自己實現 Illuminate/Cache/StoreInterface 接口。
在控制臺創建了緩存空間之后,會有唯一的“緩存空間名稱”,然后通過 Alibaba::Cache('緩存空間名稱') 來獲得 Cache 對象。以下就是實現 ACE 緩存服務驅動的步驟:
1.為了方便修改,我在配置文件 app/config/cache.php 中增加一個名為 ace 的鍵,存儲緩存空間名稱。
2.然后創建一個 AceMemcachedStore 類,這個類實現 Illuminate/Cache/StoreInterface 接口。
3.最后,用 AceMemcachedStore 對象來創建 Illuminate/Cache/Repository 對象。
下面來看具體的代碼實現:
編碼實現自定義 ACE 緩存驅動:
第一步,修改配置文件。打開 app/config/cache.php,在最后增加一行:
復制代碼代碼如下:
// 指定緩存空間名稱
'ace' => 'lblog-cache',
第二步,為了方便,把自己的類文件放在 src/Ace 目錄下,使用 Ace 作為命名空間。
1.在 app 的同級目錄創建目錄 src/Ace。
2.打開 composer.json 文件,修改 autoload 節,在 classmap 下面用 psr-0 或者 psr-4 來自動加載文件。
復制代碼代碼如下:
"autoload": {
"classmap": [
// autoload class
],
"psr-4": {
"Ace//": "src/Ace"
}
},
創建 src/Ace/AceMemcachedStore.php 文件,代碼如下:
復制代碼代碼如下:
<?php
namespace Ace;
use Illuminate/Cache/StoreInterface;
use Illuminate/Cache/TaggableStore;
class AceMemcachedStore extends TaggableStore implements StoreInterface {
protected $memcached;
protected $prefix;
public function __construct($space, $prefix = '') {
$this->memcached = /Alibaba::Cache($space);
$this->prefix = strlen($prefix) > 0 ? $prefix.':' : '';
}
/**
* Retrieve an item from the cache by key.
*
* @param string $key
* @return mixed
*/
public function get($key)
{
$value = $this->memcached->get($this->prefix.$key);
if(is_bool($value) && $value === false) {
return null;
}
return $value;
}
/**
* Store an item in the cache for a given number of minutes.
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return boolean
*/
public function put($key, $value, $minutes)
{
return $this->memcached->set($this->prefix.$key, $value, $minutes);
}
/**
* Increment the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return boolean
*/
public function increment($key, $value = 1)
{
return $this->memcached->increment($this->prefix.$key, $value);
}
/**
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
* @return boolean
*/
public function decrement($key, $value = 1)
{
return $this->memcached->decrement($this->prefix.$key, $value);
}
/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return boolean
*/
public function forever($key, $value)
{
return $this->memcached->set($key, $value, 0);
}
/**
* Remove an item from the cache.
*
* @param string $key
* @return boolean
*/
public function forget($key)
{
return $this->memcached->delete($this->prefix.$key);
}
/**
* Remove all items from the cache.
*
* @return void
*/
public function flush()
{
//$this->memcached->flush();
return false;
}
public function getMemcached()
{
return $this->memcached;
}
/**
* Get the cache key prefix.
*
* @return string
*/
public function getPrefix()
{
return $this->prefix;
}
}
這段代碼比較簡單,不過要特別注意一下 get($key) 方法的實現。標準 memcached 以及 ACE 的緩存對象的 get 方法都是key有效時返回對應的緩存值,否則返回false,而在 Laravel 4 中,是通過檢測 get 方法返回的是否 null 來做判斷,所以這里需要處理一下,返回緩存值或者null。
AceMemcachedStore類已經創建好了,接下來在 bootstrap/start.php 文件中擴展 Cache:
打開 bootstrap/start.php, 添加以下代碼:
復制代碼代碼如下:
// 擴展名為 ace 的緩存驅動
Cache::extend('ace', function($app)
{
// 從 app/config/cache.php 文件中讀取 "ace" 的值
$space = $app['config']['cache.ace'];
// 從 app/config/cache.php 文件中讀取 "prefix" 的值
$prefix = $app['config']['cache.prefix'];
// 創建 /Ace/AceMemcachedStore 對象
$store = new /Ace/AceMemcachedStore($space, $prefix);
// 創建并返回 /Illuminate/Cache/Repository 對象
return new /Illuminate/Cache/Repository($store);
});
指定系統使用 'ace' 作為緩存驅動:打開 app/config/cache.php,找到 'driver' => '...' 所在行,修改為:'driver' => 'ace'.
使用和限制
通過以上操作,就可以在 Laravel 4 中調用 ACE 的緩存服務,使用上與平常的用法完全一致,比如:
復制代碼代碼如下:
// 添加緩存,有效時間10分鐘
Cache::put('my_key', 'my value', 10);
// 讀取緩存
Cache::get('my_key')
// 判斷緩存是否存在
Cache::has('my_key')
// 數據查詢緩存
$users = DB::table('users')->remember(10)->get();
但是由于 ACE 緩存對象本身的限制,只能刪除指定 key 的緩存對象,不能遍歷、全量操作,因此 Cache::flush() 方法就不能使用。在上面的 AceMemcachedStore 對象中,flush 方法沒有做任何操作,只是返回 false.