* * * * *
[TOC]
## 配置
Laravel 為各種后端緩存提供豐富而統一的 API,而其配置信息位于?`config/cache.php`?文件中,你可以指定默認的緩存驅動程序。Laravel 支持當前流行的后端緩存,例如?[Memcached](https://memcached.org/)?和?[Redis](https://redis.io/)。
緩存配置文件還包含各種其他選項,這些選項都記錄在文件中,因此請確保閱讀這些選項。 默認情況下,Laravel 配置為使用?`file`?緩存驅動程序,它將序列化的緩存對象存儲在文件系統中。 對于較大的應用程序,建議您使用更強大的驅動程序,例如 Memcached 或 Redis。 你甚至可以為同一個驅動程序配置多個緩存配置。
### 驅動的前提條件
#### 數據庫
當使用?`database`?緩存驅動時,你需要配置一個表來存放緩存數據,下面是構建緩存數據表結構的?`Schema`?聲明示例:
~~~
Schema::create('cache', function ($table) {
$table->string('key')->unique();
$table->text('value');
$table->integer('expiration');
});
~~~
> {tip} 你也可以使用 Artisan 命令?`php artisan cache:table`?來生成合適的遷移。
#### Memcached
使用 Memcached 驅動需要安裝?[Memcached PECL 擴展包](https://pecl.php.net/package/memcached)?。你可以把所有 Memcached 服務器都列在?`config/cache.php`?配置文件中:
~~~
'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
在使用 Laravel 的 Redis 緩存之前,你需要通過 Composer 安裝?`predis/predis`?擴展包 (~1.0) 或者使用 PECL 安裝 PhpRedis PHP 拓展。
如需了解更多配置 Redis 的信息,請參考?[Laravel Redis 文檔](http://www.hmoore.net/tonyyu/laravel_5_6/786265#_2)。
## 緩存的使用
### 獲取緩存實例
`Illuminate\Contracts\Cache\Factory`?和?`Illuminate\Contracts\Cache\Repository`?[契約](http://www.hmoore.net/tonyyu/laravel_5_6/786059)?提供了 Laravel 緩存服務的訪問機制。?`Factory`?契約為你的應用程序定義了訪問所有緩存驅動的機制。?`Repository`?契約通常是由?`cache`?配置文件指定的默認緩存驅動實現的。
不過,你也可以使用?`Cache`?Facade,我們將在后續的文檔中介紹。`Cache`?Facade 為 Laravel 緩存契約底層的實現提供了方便又簡潔的方法:
~~~
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Cache;
class UserController extends Controller
{
/**
* 顯示應用程序的所有用戶的列表。
*
* @return Response
*/
public function index()
{
$value = Cache::get('key');
//
}
}
~~~
#### 訪問多個緩存存儲
使用?`Cache`?Facade,你可以通過?`store`?方法來訪問各種緩存存儲。 傳入?`store`?方法的鍵應該對應?`cache`配置信息文件中的?`stores`?配置數組中所列的存儲之一:
~~~
$value = Cache::store('file')->get('foo');
Cache::store('redis')->put('bar', 'baz', 10);
~~~
### 從緩存中獲取數據
`Cache`?Facade 中的?`get`?方法是用來從緩存中獲取數據的方法。如果該數據不存在于緩存中,則該方法返回?`null`。你也可以向?`get`?方法傳遞第二個參數,用來指定如果查找的數據不存在時,你希望返回的默認值:
~~~
$value = Cache::get('key');
$value = Cache::get('key', 'default');
~~~
你甚至可以傳遞?`Closure`?作為默認值。如果指定的數據不存在于緩存中,將返回?`Closure`?的結果。傳遞閉包的方法可以允許你從數據庫或其他外部服務中獲取默認值:
~~~
$value = Cache::get('key', function () {
return DB::table(...)->get();
});
~~~
#### 確認項目是否存在
`has`?方法可用于確定緩存中是否存在項目。如果值為?`null`?或?`false`,則此方法將返回?`false`:
~~~
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`?方法的?`Closure`?將被執行,然后將其結果返回并放置在緩存中。
你還可以使用?`rememberForever`?方法從緩存中查找數據或永久存儲它:
~~~
$value = Cache::rememberForever('users', function() {
return DB::table('users')->get();
});
~~~
#### 獲取和刪除
如果你需要從緩存中獲取到數據之后再刪除它,你可以使用?`pull`?方法。和?`get`?方法一樣,如果緩存中不存在該數據, 則返回?`null`?:
~~~
$value = Cache::pull('key');
~~~
### 在緩存中存儲數據
你可以使用?`Cache`?Facade 的?`put`?方法來將數據存儲到緩存中。當你在緩存中存放數據時,你需要使用第三個參數來設定緩存的過期時間:
~~~
Cache::put('key', 'value', $minutes);
~~~
除了以整數形式傳遞過期的分鐘數,還可以傳遞一個?`DateTime`?實例來表示該數據的過期時間:
~~~
$expiresAt = now()->addMinutes(10);
Cache::put('key', 'value', $expiresAt);
~~~
#### 只存儲沒有的數據
`add`?方法將不存在于緩存中的數據放入緩存中,如果存放成功返回?`true`?,否則返回?`false`?:
~~~
Cache::add('key', 'value', $minutes);
~~~
#### 數據永久存儲
`forever`?方法可以用來將數據永久存入緩存中。因為這些緩存數據不會過期,所以必須通過?`forget`?方法從緩存中手動刪除它們:
~~~
Cache::forever('key', 'value');
~~~
> {tip} 如果你使用 Memcached 驅動,那么當緩存數量達到其大小限制時,可能會刪除「永久」存儲的數據。
### 刪除緩存中的數據
你可以使用?`forget`?方法從緩存中刪除數據:
~~~
Cache::forget('key');
~~~
你也可以使用?`flush`?方法清空所有緩存:
~~~
Cache::flush();
~~~
> {note} 清空緩存的方法并不會考慮緩存前綴,會將緩存中所有的內容刪除。因此在清除與其它應用程序共享的緩存時請謹慎考慮。
### Cache 輔助函數
除了可以使用?`Cache`?Facade 或者?[Cache 契約](http://www.hmoore.net/tonyyu/laravel_5_6/786059)?之外,你也可以使用全局幫助函數?`cache`?來獲取和保存緩存數據。當?`cache`?只接收一個字符串參數的時候,它將會返回給定鍵對應的值:
~~~
$value = cache('key');
~~~
如果你向函數提供了一組鍵值對和到期時間,它會在指定時間內在緩存中存儲數據:
~~~
cache(['key' => 'value'], $minutes);
cache(['key' => 'value'], now()->addSeconds(10));
~~~
> {tip} 如果在測試中使用全局函數?`cache`,可以使用?`Cache::shouldReceive`?方法,就像正在?[測試 Facade](http://www.hmoore.net/tonyyu/laravel_5_6/786285#Facades_248)?一樣。
## 緩存標記
> {note} 緩存標記并不支持使用?`file`?或?`database`?的緩存驅動。此外,當在「永久」存儲的高速緩存中使用多個標記時,類似?`memcached`這種驅動的性能會是最好的,它會自動清除舊的記錄。
### 寫入被標記的緩存數據
所謂的緩存標記,就是對緩存的數據打上相關的標記,以便清空所有被分配指定標記的緩存值。你可以通過傳入標記名稱的有序數組來為緩存數據寫入標記。例如,我們可以將值?`put`?進緩存的同時標記它:
~~~
Cache::tags(['people', 'artists'])->put('John', $john, $minutes);
Cache::tags(['people', 'authors'])->put('Anne', $anne, $minutes);
~~~
### 訪問被標記的緩存數據
若要獲取一個被標記的緩存數據,請將相同的有序標記數組傳遞給?`tags`?方法,然后調用?`get`?方法來獲取你要檢索的鍵:
~~~
$john = Cache::tags(['people', 'artists'])->get('John');
$anne = Cache::tags(['people', 'authors'])->get('Anne');
~~~
### 移除被標記的緩存數據
你可以清空有單個標記或是一組標記的所有緩存數據。例如,下面的語句會刪除被標記為?`people`、`authors`?或兩者都有的緩存。所以,`Anne`?與?`John`?都會從緩存被刪除:
~~~
Cache::tags(['people', 'authors'])->flush();
~~~
相比之下,下面的語句只會刪除被標記為?`authors`?的緩存,所以?`Anne`?會被移除,但?`John`?不會:
~~~
Cache::tags('authors')->flush();
~~~
## 增加自定義的緩存驅動
### 寫驅動
要創建自定義的緩存驅動程序,首先需要實現?`Illuminate\Contracts\Cache\Store`?[契約](http://www.hmoore.net/tonyyu/laravel_5_6/786059)?。因此,MongoDB 的緩存實現看起來會像這樣:
~~~
<?php
namespace App\Extensions;
use Illuminate\Contracts\Cache\Store;
class MongoStore implements Store
{
public function get($key) {}
public function many(array $keys);
public function put($key, $value, $minutes) {}
public function putMany(array $values, $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 的連接來實現這些方法。關于如何實現這些方法的示例,可以參閱框架源代碼中的?`Illuminate\Cache\MemcachedStore`。一旦我們完成方法的實現,可以像下面這樣完成自定義驅動的注冊了。
~~~
Cache::extend('mongo', function ($app) {
return Cache::repository(new MongoStore);
});
~~~
> {tip} 如果你想自定義的緩存驅動代碼的放置,你可以在?`app`?目錄下創建一個?`Extensions`?命名空間。Laravel 沒有硬性規定應用程序的結構,你可以根據自己的喜好自由組織你的應用程序。
### 注冊驅動
要使用 Laravel 來注冊自定義的緩存驅動,就要在?`Cache`?Facade 上使用?`extend`?方法。對?`Cache::extend`?的調用可以在最新的 Laravel 應用程序中附帶的?`App\Providers\AppServiceProvider`?的?`boot`?方法中完成,或者你可以創建自己的服務提供器來放置這些擴展,只是不要忘記在?`config/app.php`?中的?`providers`?數組中注冊提供器:
~~~
<?php
namespace App\Providers;
use App\Extensions\MongoStore;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;
class CacheServiceProvider extends ServiceProvider
{
/**
* 執行服務的注冊后引導。
*
* @return void
*/
public function boot()
{
Cache::extend('mongo', function ($app) {
return Cache::repository(new MongoStore);
});
}
/**
* 在容器中注冊綁定。
*
* @return void
*/
public function register()
{
//
}
}
~~~
傳遞給?`extend`?方法的第一個參數是驅動程序的名稱。這將與?`config/cache.php`?配置文件的?`driver`?選項相對應。第二個參數是應該返回?`Illuminate\Cache\Repository`?實例的閉包。這個閉包將傳遞一個?[服務容器](http://www.hmoore.net/tonyyu/laravel_5_6/786056)?的?`$app`?實例。
你的自定義的擴展注冊后,需要將?`config/cache.php`?配置文件中的?`driver`?選項更新為你的擴展名。
## 事件
你可以監聽緩存觸發的?[事件](http://www.hmoore.net/tonyyu/laravel_5_6/786242)?來對每個緩存的操作執行代碼。為此,你應該要將這些事件監聽器放在?`EventServiceProvider`?中:
~~~
/**
* 應用程序的事件偵聽器映射。
*
* @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',
],
];
~~~
- 前言
- 翻譯說明
- 發行說明
- 升級指南
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- Homestead
- Valet
- 部署
- 核心架構
- 請求周期
- 服務容器
- 服務提供者
- Facades
- Contracts
- 基礎功能
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- URL
- Session
- 表單驗證
- 錯誤
- 日志
- 前端開發
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全相關
- 用戶認證
- Passport OAuth 認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- API 資源
- 序列化
- 測試相關
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Horizon
- Scout 全文搜索
- Socialite 社會化登錄