Laravel為不同的緩存系統(tǒng)提供了統(tǒng)一的API。緩存配置位于config/cache.php
。在該文件中你可以指定在應(yīng)用中默認(rèn)使用哪個(gè)緩存驅(qū)動(dòng)。Laravel目前支持流行的緩存后端如Memcached和Redis等。
緩存配置文件還包含其他文檔化的選項(xiàng),確保仔細(xì)閱讀這些選項(xiàng)。默認(rèn)情況下,Laravel被配置成使用文件緩存,這會(huì)將序列化數(shù)據(jù)和緩存對(duì)象存儲(chǔ)到文件系統(tǒng)。對(duì)大型應(yīng)用,建議使用內(nèi)存緩存如Memcached或APC,你甚至可以為同一驅(qū)動(dòng)配置多個(gè)緩存配置。
使用database
緩存驅(qū)動(dòng)時(shí),你需要設(shè)置一張表包含緩存緩存項(xiàng)。下面是該表的Schema
聲明:
Schema::create('cache', function($table) {
$table->string('key')->unique();
$table->text('value');
$table->integer('expiration');
});
使用Memcached緩存要求安裝了Memcached PECL 包,即PHP Memcached擴(kuò)展。
Memcached::addServer默認(rèn)配置使用TCP/IP協(xié)議:
'memcached' => [
[
'host' => '127.0.0.1',
'port' => 11211,
'weight' => 100
],
],
你還可以設(shè)置host
?選項(xiàng)為UNIX socket路徑,如果你這樣做,port
選項(xiàng)應(yīng)該置為0:
'memcached' => [
[
'host' => '/var/run/memcached/memcached.sock',
'port' => 0,
'weight' => 100
],
],
使用Laravel的Redis緩存之前,你需要通過(guò)Composer安裝predis/predis
包(~1.0)。
了解更多關(guān)于Redis的配置,查看Larave的Redis文檔。
Illuminate\Contracts\Cache\Factory
和Illuminate\Contracts\Cache\Repository
契約提供了訪問(wèn)Laravel的緩存服務(wù)的方法。Factory
契約提供了所有訪問(wèn)應(yīng)用定義的緩存驅(qū)動(dòng)的方法。Repository
契約通常是應(yīng)用中cache
配置文件中指定的默認(rèn)緩存驅(qū)動(dòng)的一個(gè)實(shí)現(xiàn)。
然而,你還可以使用Cache
門(mén)面,這也是我們?cè)谡麄€(gè)文檔中使用的方式,Cache
門(mén)面提供了簡(jiǎn)單方便的方式對(duì)底層Laravel緩存契約實(shí)現(xiàn)進(jìn)行訪問(wèn)。
例如,讓我們?cè)诳刂破髦袑?dǎo)入Cache
門(mén)面:
<?php
namespace App\Http\Controllers;
use Cache;
use Illuminate\Routing\Controller;
class UserController extends Controller{
/**
* 顯示應(yīng)用所有用戶列表
*
* @return Response
*/
public function index()
{
$value = Cache::get('key');
//
}
}
使用Cache
門(mén)面,你可以使用store
方法訪問(wèn)不同的緩存存儲(chǔ)器,傳入store
方法的鍵就是cache配置文件中stores
配置數(shù)組里列出的相應(yīng)的存儲(chǔ)器:
$value = Cache::store('file')->get('foo');
Cache::store('redis')->put('bar', 'baz', 10);
Cache
門(mén)面的get
方法用于從緩存中獲取緩存項(xiàng),如果緩存項(xiàng)不存在,返回null。如果需要的話你可以傳遞第二個(gè)參數(shù)到get
方法指定緩存項(xiàng)不存在時(shí)返回的自定義默認(rèn)值:
$value = Cache::get('key');
$value = Cache::get('key', 'default');
你甚至可以傳遞一個(gè)閉包作為默認(rèn)值,如果緩存項(xiàng)不存在的話閉包的結(jié)果將會(huì)被返回。傳遞閉包允許你可以從數(shù)據(jù)庫(kù)或其它外部服務(wù)獲取默認(rèn)值:
$value = Cache::get('key', function() {
return DB::table(...)->get();
});
has
方法用于判斷緩存項(xiàng)是否存在:
if (Cache::has('key')) {
//
}
increment
和decrement
方法可用于調(diào)整緩存中的整型數(shù)值。這兩個(gè)方法都可以接收第二個(gè)參數(shù)來(lái)指明緩存項(xiàng)數(shù)值增加和減少的數(shù)目:
Cache::increment('key');
Cache::increment('key', $amount);
Cache::decrement('key');
Cache::decrement('key', $amount);
有時(shí)候你可能想要獲取緩存項(xiàng),但如果請(qǐng)求的緩存項(xiàng)不存在時(shí)給它存儲(chǔ)一個(gè)默認(rèn)值。例如,你可能想要從緩存中獲取所有用戶,或者如果它們不存在的話,從數(shù)據(jù)庫(kù)獲取它們并將其添加到緩存中,你可以通過(guò)使用Cache::remember
方法實(shí)現(xiàn):
$value = Cache::remember('users', $minutes, function() {
return DB::table('users')->get();});
如果緩存項(xiàng)不存在,傳遞給remember
方法的閉包被執(zhí)行并且將結(jié)果存放到緩存中。
你還可以聯(lián)合remember
和forever
方法:
$value = Cache::rememberForever('users', function() {
return DB::table('users')->get();});
如果你需要從緩存中獲取緩存項(xiàng)然后刪除,你可以使用pull
方法,和get
方法一樣,如果緩存項(xiàng)不存在的話返回null:
$value = Cache::pull('key');
你可以使用Cache
?門(mén)面上的put
方法在緩存中存儲(chǔ)緩存項(xiàng)。當(dāng)你在緩存中存儲(chǔ)緩存項(xiàng)的時(shí)候,你需要指定數(shù)據(jù)被緩存的時(shí)間(分鐘數(shù)):
Cache::put('key', 'value', $minutes);
除了傳遞緩存項(xiàng)失效時(shí)間,你還可以傳遞一個(gè)代表緩存項(xiàng)有效時(shí)間的PHP?Datetime
實(shí)例:
$expiresAt = Carbon::now()->addMinutes(10);
Cache::put('key', 'value', $expiresAt);
add
方法只會(huì)在緩存項(xiàng)不存在的情況下添加緩存項(xiàng)到緩存,如果緩存項(xiàng)被添加到緩存返回true
,否則,返回false
:
Cache::add('key', 'value', $minutes);
forever
方法用于持久化存儲(chǔ)緩存項(xiàng)到緩存,這些值必須通過(guò)forget
方法手動(dòng)從緩存中移除:
Cache::forever('key', 'value');
你可以使用Cache
門(mén)面上的forget
方法從緩存中移除緩存項(xiàng):
Cache::forget('key');
要使用自定義驅(qū)動(dòng)擴(kuò)展Laravel緩存,我們使用Cache
門(mén)面的extend
方法,該方法用于綁定定義驅(qū)動(dòng)解析器到管理器,通常,這可以在服務(wù)提供者中完成。
例如,要注冊(cè)一個(gè)新的命名為“mongo”的緩存驅(qū)動(dòng):
<?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
方法的第一個(gè)參數(shù)是驅(qū)動(dòng)名稱。該值對(duì)應(yīng)配置文件config/cache.php
中的driver
選項(xiàng)。第二個(gè)參數(shù)是返回Illuminate\Cache\Repository
實(shí)例的閉包。該閉包中被傳入一個(gè)$app
實(shí)例,也就是服務(wù)容器的一個(gè)實(shí)例。
調(diào)用Cache::extend
可以在默認(rèn)App\Providers\AppServiceProvider
中的boot
方法中完成,或者你也可以創(chuàng)建自己的服務(wù)提供者來(lái)存放該擴(kuò)展——只是不要忘了在配置文件config/app.php
中注冊(cè)該提供者。
要?jiǎng)?chuàng)建自定義的緩存驅(qū)動(dòng),首先需要實(shí)現(xiàn)Illuminate\Contracts\Cache\Store
契約,所以,我們的MongoDB
緩存實(shí)現(xiàn)看起來(lái)像這樣子:
<?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
連接實(shí)現(xiàn)每一個(gè)方法,實(shí)現(xiàn)完成后,我們可以完成自定義驅(qū)動(dòng)注冊(cè):
Cache::extend('mongo', function($app) {
return Cache::repository(new MongoStore);
});
擴(kuò)展完成后,只需要更新配置文件config/cache.php
的driver
選項(xiàng)為你的擴(kuò)展名稱。
如果你在擔(dān)心將自定義緩存驅(qū)動(dòng)代碼放到哪,考慮將其放到Packgist!或者,你可以在app
目錄下創(chuàng)建一個(gè)Extensions
命名空間。然而,記住Laravel并沒(méi)有一個(gè)嚴(yán)格的應(yīng)用目錄結(jié)構(gòu),你可以基于你的需要自由的組織目錄結(jié)構(gòu)。
注意:緩存標(biāo)簽不支持
file
或database
緩存驅(qū)動(dòng),此外,在“永久”存儲(chǔ)緩存中使用多個(gè)標(biāo)簽時(shí),memcached
之類的驅(qū)動(dòng)有著最佳性能,因?yàn)樗梢宰詣?dòng)清除過(guò)期的記錄。
緩存標(biāo)簽允許你給相關(guān)的緩存項(xiàng)打上同一個(gè)標(biāo)簽,然后可以輸出被分配同一個(gè)標(biāo)簽的所有緩存值。你可以通過(guò)傳遞一個(gè)有序的標(biāo)簽名數(shù)組來(lái)訪問(wèn)被打上標(biāo)簽的緩存。例如,讓我們?cè)L問(wèn)一個(gè)被打上標(biāo)簽的緩存并將其值放到緩存中:
Cache::tags(['people', 'artists'])->put('John', $john, $minutes);
Cache::tags(['people', 'authors'])->put('Anne', $anne, $minutes);
然而,并不只限于使用put
方法,你可以在處理標(biāo)簽時(shí)使用任何混存存儲(chǔ)器提供的方法。
要獲取被打上標(biāo)簽的緩存項(xiàng),傳遞同樣的有序標(biāo)簽名數(shù)組到tags
方法:
$john = Cache::tags(['people', 'artists'])->get('John');
$anne = Cache::tags(['people', 'authors'])->get('Anne');
通過(guò)上面的語(yǔ)句你可以輸出所有分配了該標(biāo)簽或標(biāo)簽列表的緩存項(xiàng),例如,下面這個(gè)語(yǔ)句將會(huì)移除被打上people
,authors
標(biāo)簽的緩存,或者,Anne
?和?John
都會(huì)從緩存中移除:
Cache::tags(['people', 'authors'])->flush();
相比之下,下面這個(gè)語(yǔ)句只會(huì)移除被打上?authors
標(biāo)簽的緩存,所以John
會(huì)被移除,而Anne
不會(huì):
Cache::tags('authors')->flush();
要在每次緩存操作時(shí)執(zhí)行代碼,你可以監(jiān)聽(tīng)緩存觸發(fā)的事件,通常,你可以將這些緩存處理器代碼放到EventServiceProvider
的boot
方法中:
/**
* 注冊(cè)應(yīng)用任意其他事件
*
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @return void
*/
public function boot(DispatcherContract $events){
parent::boot($events);
$events->listen('cache.hit', function ($key, $value) {
//
});
$events->listen('cache.missed', function ($key) {
//
});
$events->listen('cache.write', function ($key, $value, $minutes) {
//
});
$events->listen('cache.delete', function ($key) {
//
});
}
更多建議: