[TOC]
### **1、配置**
[Laravel](http://laravelacademy.org/tags/laravel "View all posts in Laravel")?為不同的[緩存](http://laravelacademy.org/tags/%e7%bc%93%e5%ad%98 "View all posts in 緩存")系統提供了統一的 API。緩存配置位于?`config/cache.php`。在該文件中你可以指定在應用中默認使用哪個緩存驅動。Laravel 目前支持主流的緩存后端如?[Memcached](http://memcached.org/)?和?[Redis](http://redis.io/)?等。
緩存配置文件還包含其他[文檔](http://laravelacademy.org/tags/%e6%96%87%e6%a1%a3 "View all posts in 文檔")化的選項,確保仔細閱讀這些選項。默認情況下,Laravel 被配置成使用[文件緩存](http://laravelacademy.org/tags/%e6%96%87%e4%bb%b6%e7%bc%93%e5%ad%98 "View all posts in 文件緩存"),這會將序列化數據和緩存對象存儲到文件系統。對大型應用,建議使用內存緩存如?[Memcached](http://laravelacademy.org/tags/memcached "View all posts in Memcached")?或 APC,你甚至可以為同一驅動配置多個緩存配置。
#### **1.1 緩存預備知識**
##### **[數據庫](http://laravelacademy.org/tags/%e6%95%b0%e6%8d%ae%e5%ba%93 "View all posts in 數據庫")**
使用?`database`?緩存驅動時,你需要設置一張表包含緩存緩存項。下面是該表的?`Schema`?聲明:
~~~
Schema::create('cache', function($table) {
$table->string('key')->unique();
$table->text('value');
$table->integer('expiration');
});
~~~
##### **Memcached**
使用 Memcached 緩存要求安裝了[Memcached PECL 包](http://pecl.php.net/package/memcached),即 PHP Memcached?[擴展](http://laravelacademy.org/tags/%e6%89%a9%e5%b1%95 "View all posts in 擴展")。
[Memcached::addServer](http://php.net/manual/en/memcached.addserver.php)默認配置使用 TCP/IP 協議:
~~~
'memcached' => [
[
'host' => '127.0.0.1',
'port' => 11211,
'weight' => 100
],
],
~~~
你還可以設置?`host`?選項為 UNIX socket 路徑,如果你這樣做,`port`?選項應該置為?`0`:
~~~
'memcached' => [
[
'host' => '/var/run/memcached/memcached.sock',
'port' => 0,
'weight' => 100
],
],
~~~
##### **[Redis](http://laravelacademy.org/tags/redis "View all posts in Redis")**
使用 Laravel 的 Redis 緩存之前,你需要通過 Composer 安裝?`predis/predis`?包(~1.0)。
想要了解更多關于 Redis 的配置,查看[Larave的Redis文檔](http://laravelacademy.org/post/228.html)。
### **2、緩存使用**
#### **2.1 獲取緩存實例**
`Illuminate\Contracts\[Cache](http://laravelacademy.org/tags/cache "View all posts in Cache")\Factory`?和?`Illuminate\Contracts\Cache\Repository`?契約提供了訪問 Laravel 的緩存服務的方法。`Factory`?契約提供了所有訪問應用定義的緩存驅動的方法。`Repository`?契約通常是應用中`cache`?配置文件中指定的默認緩存驅動的一個實現。
然而,你還可以使用?`Cache`?[門面](http://laravelacademy.org/post/2920.html),這也是我們在整個文檔中使用的方式,`Cache`?門面提供了簡單方便的方式對底層 Laravel 緩存契約實現進行訪問。
例如,讓我們在控制器中導入?`Cache`?門面:
~~~
<?php
namespace App\Http\Controllers;
use Cache;
use Illuminate\Routing\Controller;
class UserController extends Controller{
/**
* 顯示應用所有用戶列表
*
* @return Response
*/
public function index()
{
$value = Cache::get('key');
//
}
}
~~~
##### **訪問多個緩存存儲**
使用?`Cache`?門面,你可以使用?`store`?方法訪問不同的緩存存儲器,傳入?`store`?方法的鍵就是 cache 配置文件中`stores`?配置數組里列出的相應的存儲器:
~~~
$value = Cache::store('file')->get('foo');
Cache::store('redis')->put('bar', 'baz', 10);
~~~
#### **2.2 從緩存中獲取數據**
`Cache`?門面的?`get`?方法用于從緩存中獲取緩存項,如果緩存項不存在,返回 null。如果需要的話你可以傳遞第二個參數到?`get`?方法指定緩存項不存在時返回的自定義默認值:
~~~
$value = Cache::get('key');
$value = Cache::get('key', 'default');
~~~
你甚至可以傳遞一個閉包作為默認值,如果緩存項不存在的話閉包的結果將會被返回。傳遞閉包允許你可以從數據庫或其它外部服務獲取默認值:
~~~
$value = Cache::get('key', function() {
return DB::table(...)->get();
});
~~~
##### **檢查緩存項是否存在**
`has`?方法用于判斷緩存項是否存在:
~~~
if (Cache::has('key')) {
//
}
~~~
##### **數值增加/減少**
`increment`?和?`decrement`?方法可用于調整緩存中的整型數值。這兩個方法都可以接收第二個參數來指明緩存項數值增加和減少的數目:
~~~
Cache::increment('key');
Cache::increment('key', $amount);
Cache::decrement('key');
Cache::decrement('key', $amount);
~~~
##### **獲取或更新**
有時候你可能想要獲取緩存項,但如果請求的緩存項不存在時給它存儲一個默認值。例如,你可能想要從緩存中獲取所有用戶,或者如果它們不存在的話,從數據庫獲取它們并將其添加到緩存中,你可以通過使用?`Cache::remember`?方法實現:
~~~
$value = Cache::remember('users', $minutes, function() {
return DB::table('users')->get();
});
~~~
如果緩存項不存在,傳遞給?`remember`?方法的閉包被執行并且將結果存放到緩存中。
你還可以聯合?`remember`?和?`forever`?方法:
~~~
$value = Cache::rememberForever('users', function() {
return DB::table('users')->get();
});
~~~
##### **獲取并刪除**
如果你需要從緩存中獲取緩存項然后刪除,你可以使用?`pull`?方法,和?`get`?方法一樣,如果緩存項不存在的話返回null:
~~~
$value = Cache::pull('key');
~~~
#### **2.3 存儲緩存項到緩存**
你可以使用?`Cache`?門面上的?`put`?方法在緩存中存儲緩存項。當你在緩存中存儲緩存項的時候,你需要指定數據被緩存的時間(分鐘數):
~~~
Cache::put('key', 'value', $minutes);
~~~
除了傳遞緩存項失效時間,你還可以傳遞一個代表緩存項有效時間的PHP?`Datetime`實例:
~~~
$expiresAt = Carbon::now()->addMinutes(10);
Cache::put('key', 'value', $expiresAt);
~~~
`add`?方法只會在緩存項不存在的情況下添加緩存項到緩存,如果緩存項被添加到緩存返回?`true`,否則,返回`false`:
~~~
Cache::add('key', 'value', $minutes);
~~~
`forever`?方法用于持久化存儲緩存項到緩存,這些值必須通過?`forget`?方法手動從緩存中移除:
~~~
Cache::forever('key', 'value');
~~~
#### **2.4 從緩存中移除數據**
你可以使用?`Cache`?門面上的?`forget`?方法從緩存中移除緩存項:
~~~
Cache::forget('key');
~~~
還可以使用?`flush`?方法清除所有緩存:
~~~
Cache::flush();
~~~
清除緩存并不管什么緩存鍵前綴,而是從緩存系統中移除所有數據,所以在使用這個方法時如果其他應用與本應用有共享緩存時需要格外注意。
### **3、緩存[標簽](http://laravelacademy.org/tags/%e6%a0%87%e7%ad%be "View all posts in 標簽")**
注意:緩存標簽目前不支持?`file`?或?`database`?緩存驅動,此外,當使用多標簽的緩存被設置為永久存儲時,使用`memcached`?驅動的緩存有著最佳性能表現,因為 Memcached 會自動清除陳舊記錄。
#### **3.1 存儲被打上標簽的緩存項**
緩存標簽允許你給相關緩存項打上同一個標簽以便于后續清除這些緩存值,被打上標簽的緩存可以通過傳遞一個被排序的標簽數組來訪問。例如,我們可以通過以下方式在添加緩存的時候設置標簽:
~~~
Cache::tags(['people', 'artists'])->put('John', $john, $minutes);Cache::tags(['people', 'authors'])->put('Anne', $anne, $minutes);
~~~
你可以給多個緩存項打上相同標簽,這是沒有數目限制的。
#### **3.2 訪問被打上標簽的緩存項**
要獲取被打上標簽的緩存項,傳遞同樣的有序標簽數組到?`tags`?方法:
~~~
$john = Cache::tags(['people', 'artists'])->get('John');$anne = Cache::tags(['people', 'authors'])->get('Anne');
~~~
你可以同時清除被打上同一標簽/標簽列表的所有緩存項,例如,以下語句會移除被打上?`people`?或?`authors`?標簽的所有緩存:
~~~
Cache::tags(['people', 'authors'])->flush();
~~~
這樣,上面設置的?`Anne`?和?`John`?緩存項都會從緩存中移除。
相反,以下語句只移除被打上?`authors`?標簽的語句,所以只有?`Anne`?會被移除而?`John`?不會:
~~~
Cache::tags('authors')->flush();
~~~
### **4、添加自定義緩存驅動**
要使用自定義驅動擴展 Laravel 緩存,可以使用?`Cache`?門面提供的?`extend`?方法,該方法用于綁定定義驅動解析器到管理器,通常,這可以在[服務提供者](http://laravelacademy.org/post/2900.html)中完成。
例如,要注冊一個新的命名為“mongo”的緩存驅動:
~~~
<?php
namespace App\Providers;
use Cache;
use App\Extensions\MongoStore;
use Illuminate\Support\ServiceProvider;
class CacheServiceProvider extends ServiceProvider{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
Cache::extend('mongo', function($app) {
return Cache::repository(new MongoStore);
});
}
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
//
}
}
~~~
傳遞給?`extend`?方法的第一個參數是驅動名稱。該值對應配置文件?`config/cache.php`?中的?`driver`?選項。第二個參數是返回`Illuminate\Cache\Repository`?實例的閉包。該閉包中被傳入一個?`$app`?實例,也就是[服務容器](http://laravelacademy.org/post/2910.html)的一個實例。
調用?`Cache::extend`?可以在默認?`App\Providers\AppServiceProvider`?中的?`boot`?方法中完成,或者你也可以創建自己的服務提供者來存放該擴展——只是不要忘了在配置文件?`config/app.php`?中注冊該提供者。
要創建自定義的緩存驅動,首先需要實現?`Illuminate\Contracts\Cache\Store`?契約,所以,我們的?`MongoDB`?緩存實現看起來像這樣子:
~~~
<?php
namespace App\Extensions;
class MongoStore implements \Illuminate\Contracts\Cache\Store{
public function get($key) {}
public function put($key, $value, $minutes) {}
public function increment($key, $value = 1) {}
public function decrement($key, $value = 1) {}
public function forever($key, $value) {}
public function forget($key) {}
public function flush() {}
public function getPrefix() {}
}
~~~
我們只需要使用?`MongoDB`?連接實現每一個方法,實現完成后,我們可以完成自定義驅動注冊:
~~~
Cache::extend('mongo', function($app) {
return Cache::repository(new MongoStore);
});
~~~
擴展完成后,只需要更新配置文件?`config/cache.php`?的?`driver`?選項為你的擴展名稱。
如果你在擔心將自定義緩存驅動代碼放到哪,考慮將其放到Packgist!或者,你可以在?`app`?目錄下創建一個`Extensions`?命名空間。然而,記住 Laravel 并沒有一個嚴格的應用目錄結構,你可以基于你的需要自由的組織目錄結構。
### **5、緩存[事件](http://laravelacademy.org/tags/%e4%ba%8b%e4%bb%b6 "View all posts in 事件")**
要在每次緩存操作時執行代碼,你可以監聽緩存觸發的事件,通常,你可以將這些緩存處理器代碼放到`EventServiceProvider`?中:
~~~
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'Illuminate\Cache\Events\CacheHit' => [
'App\Listeners\LogCacheHit',
],
'Illuminate\Cache\Events\CacheMissed' => [
'App\Listeners\LogCacheMissed',
],
'Illuminate\Cache\Events\KeyForgotten' => [
'App\Listeners\LogKeyForgotten',
],
'Illuminate\Cache\Events\KeyWritten' => [
'App\Listeners\LogKeyWritten',
],
];
~~~
- 序言
- 發行版本說明
- 升級指南
- 貢獻代碼
- 開始
- 安裝
- 配置
- Laravel Homestead
- 基礎
- HTTP 路由
- HTTP 中間件
- HTTP 控制器
- HTTP 請求
- HTTP 響應
- 視圖
- Blade 模板引擎
- 架構
- 一次請求的生命周期
- 應用目錄結構
- 服務提供者
- 服務容器
- 門面(Facades)
- 數據庫
- 起步
- 查詢構建器
- 遷移
- 填充數據
- Eloquent ORM
- 起步
- 關聯關系
- 集合
- 訪問器&修改器
- 序列化
- 服務
- 用戶認證
- 用戶授權
- Artisan Console
- 訂閱支付實現:Laravel Cashier
- 緩存
- 集合
- 集成前端資源:Laravel Elixir
- 加密
- 錯誤&日志
- 事件
- 文件系統/云存儲
- 哈希
- 輔助函數
- 本地化
- 郵件
- 包開發
- 分頁
- Redis
- 隊列
- Session
- Envoy Task Runner
- 任務調度
- 測試
- 驗證
- 新手入門指南
- 簡單任務管理系統
- 帶用戶功能的任務管理系統