* * * * *
[TOC]
## 配置信息
Laravel 給多種緩存系統提供豐富而統一的 API,緩存配置信息位于?`config/cache.php`,在這個文件中你可以為你的應用程序指定默認的緩存驅動,Laravel 支持當前流行的緩存系統,如非常棒的?[Memcached](http://memcached.org/)?和?[Redis](http://redis.io/)?。
緩存配置信息文件中也包括很多其他選項,你可以在文件中找到這些選項,請確保你看過這些選項說明。Laravel 默認使用將序列化緩存對象保存在文件系統中的?`file`?緩存驅動,對于大型應用程序而言,推薦你使用如 Memcached 或者 Redis 這樣更強大的緩存驅動。你甚至可以為一個驅動配置多個緩存配置信息。
### 驅動前提條件
#### 數據庫
當使用?`database`?緩存驅動時,你需要配置一個用來存放緩存項的數據庫表,下面是一個?`Schema`?數據表結構聲明的示例:
~~~
Schema::create('cache', function ($table) {
$table->string('key')->unique();
$table->text('value');
$table->integer('expiration');
});
~~~
> {tip} 你也可以使用?`php artisan cache:table`?這個 Artisan 命令生成一個有合適數據表結構的 migration 。
#### 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
在使用 Redis 作為 Laravel 的緩存驅動前,你需要通過 Composer 安裝?`predis/predis`?擴展包 (~1.0) 或者使用 PECL 安裝 PhpRedis PHP 拓展。
關于配置 Redis 的更多信息,請參考?[Laravel 文檔頁面](Redis.md)?。
## 緩存的使用
### 獲取一個緩存實例
`Illuminate\Contracts\Cache\Factory`?和?`Illuminate\Contracts\Cache\Repository`?[contracts](Contracts.md)?提供了訪問 Laravel 緩存服務的機制。`Factory`?contract 則為你的應用程序定義了訪問所有緩存驅動的機制。`Repository`?contract 是典型的用?`cache`?配置信息文件指定你的應用程序默認緩存驅動的實現。
然而,你也可以使用?`Cache`?facade,我們將在文檔的后續中介紹。`Cache`?facade 提供了方便又簡潔的方法訪問緩存實例:
~~~
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Cache;
class UserController extends Controller
{
/**
* Show a list of all users of the application.
*
* @return Response
*/
public function index()
{
$value = Cache::get('key');
//
}
}
~~~
#### 訪問多個緩存倉庫
使用`Cache`?facade,可通過?`store`?方法來訪問緩存倉庫,傳入?`store`?方法的鍵應該對應一個緩存配置信息文件中的?`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');
~~~
你甚至可以將?`閉包`?作為默認值傳遞。如果指定的緩存項在緩存中不存在,`閉包`?的結果將被返回。傳遞一個閉包允許你延遲從數據庫或外部服務中取出默認值:
~~~
$value = Cache::get('key', function () {
return DB::table(...)->get();
});
~~~
#### 確認項目是否存在
`has`?方法可以用來檢查一個項目是否存在于緩存中:
~~~
if (Cache::has('key')) {
//
}
~~~
#### 遞增與遞減值
`遞增`?和?`遞減`?方法可以用來調整緩存中整數項目值。這兩個方法都可以傳入一個可選的第二個參數,用來指示要遞增或遞減多少值:
~~~
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`?方法的閉包將會被運行,而且閉包的運行結果將會被存放在緩存中。
#### 獲取和刪除
如果你需要從緩存中獲取一個緩存項然后刪除它,你可以使用?`pull`?方法。像?`get`?方法一樣,如果緩存項在緩存中不存在,`null`?將被返回:
~~~
$value = Cache::pull('key');
~~~
### 存儲項目到緩存中
你可以使用?`Cache`?facade 的?`put`?方法來存放緩存項到緩存中,當你在緩存中存放緩存項時,你需要使用第三個參數來設定緩存的存放時間:
~~~
Cache::put('key', 'value', $minutes);
~~~
如果要指定一個緩存項過期的分鐘數,你也可以傳遞一個?`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');
~~~
> {tip} 如果你在使用 Memcached 驅動,那么當緩存達到大小限制時,那些「永久」保存的緩存項可能被移除。
### 從緩存中移除項目
你可以使用?`forget`?方法從緩存中移除一個項目:
~~~
Cache::forget('key');
~~~
也可以使用?`flush`?方法清空所有緩存:
~~~
Cache::flush();
~~~
> {note} 清空緩存并不會遵從緩存的前綴,并且會將緩存中所有的緩存項刪除。在清除與其它應用程序共享的緩存時應謹慎考慮這一點。
### Cache 幫助函數
除了可以使用?`Cache`?facade 或者?[cache contract](Contracts.md)之外,你也可以使用全局幫助函數?`cache`?來獲取和保存緩存數據。當?`cache`?只接收一個字符串參數的時候,它將會返回給定鍵對應的值:
~~~
$value = cache('key');
~~~
如果你傳給函數一個鍵值對數組和過期時間,它將會把值和過期時間保存在緩存中:
~~~
cache(['key' => 'value'], $minutes);
cache(['key' => 'value'], Carbon::now()->addSeconds(10));
~~~
> {tip} 如果在測試中使用全局函數?`cache`,你應該使用?`Cache::shouldReceive`?方法,就好像你在[測試 facade](Facades.md)一樣。
## 緩存標簽
> {note} 緩存標簽并不支持使用?`file`?或?`dababase`?的緩存驅動。此外,當在緩存使用多個標簽并「永久」寫入時,類似?`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`?[contract](Contracts.md)?。所以 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`?提供者數組中注冊提供者:
~~~
<?php
namespace App\Providers;
use App\Extensions\MongoStore;
use Illuminate\Support\Facades\Cache;
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`?實例的閉包。這個閉包將傳遞一個?[service container](控制器.md)的?`$app`?實例。
一旦你的擴展被注冊,就可以輕松的更新?`config/cache.php`?配置信息文件的?`driver`?選項為你的擴展名稱。
## 緩存事件
為了在每一次緩存操作時執行代碼,你可以監聽緩存觸發的事件?[事件](事件系統.md)?。一般來說,你必須將這些事件監聽器放置在?`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',
],
];
~~~
- 前言
- 翻譯說明
- 發行說明
- 升級說明
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- 請求周期
- 開發環境部署
- Homestead
- Valet
- 核心概念
- 服務容器
- 服務提供者
- Facades
- Contracts
- HTTP層
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- Session
- 表單驗證
- 前端
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全
- 用戶認證
- Passport OAuth 認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 錯誤與日志
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- 序列化
- 測試
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Scout 全文搜索
- Socialite 社會化登錄