laravel 基礎(chǔ)教程 —— 緩存

緩存

配置

Laravel 對多種緩存系統(tǒng)提供了統(tǒng)一的 API。緩存的配置文件存放在 config/cache.php。你可以在這個文件中指定整個應(yīng)用默認(rèn)使用何種緩存驅(qū)動。Laravel 支持當(dāng)前主流的緩存系統(tǒng)如 Memcached 和 Redis。

緩存的配置文件也包含了一些額外的配置選項,這些選項在文件中都有文檔注釋,你應(yīng)該確保自己已經(jīng)讀了這些選項注釋。默認(rèn)的,Laravel 配置使用 file 緩存驅(qū)動,該驅(qū)動會在文件系統(tǒng)中存儲序列化的緩存對象。對于大型應(yīng)用,建議使用內(nèi)存級的緩存,如 Memcached 或者 APC。你甚至可以在 laravel 中配置多種緩存配置到相同的驅(qū)動。

緩存先決條件

數(shù)據(jù)庫

當(dāng)使用 database 緩存驅(qū)動時,你需要建立一個表來包含這些緩存項。你可以根據(jù)下面的 Schema 定義來建立表文件:

Schema::create('cache', function ($table) {
  $table->string('key')->unique();
  $table->text('value');
  $table->integer('expiration'); 
});

你也可以通過使用 php artisan cache:table Artisan 命令來生成正確的緩存表結(jié)構(gòu)遷移。

Memcached

使用 Memcached 緩存需要安裝 Memcached PECL package

默認(rèn)的配置基于 Memcached::addServer 使用 TCP/IP:

'memcached' => [
  [
    'host' => '127.0.0.1',
    'port' => 11211,
    'weight' => 100
  ]
],

你也可以使用 UNIX socket 路徑來設(shè)置 host。如果你這么做,你需要設(shè)置 port0:

'memcached' => [
  [
    'host' => '/var/run/memcached/memcached.sock',
    'port' => 0,
    'weight' => 100
  ],
],

Redis

在你使用 Redis 緩存之前,你需要先通過 Composer 安裝 predis/predis
關(guān)于更多的 Redis 配置信息,你可以參考 Laravel documentation page

緩存使用

獲取緩存實例

Illuminate\Contracts\Cache\FactoryIlluminate\Contracts\Cache\Repository 契約提供對 Laravel 緩存服務(wù)的訪問。Factory 契約提供了應(yīng)用中所有緩存驅(qū)動的定義。Repository 契約通常是一個基于你的 cache 配置文件所使用的默認(rèn)緩存驅(qū)動的實現(xiàn)。

事實上,你也可以使用 Cache 假面,在這篇文檔中,我們都是使用 Cache 假面進(jìn)行舉例。Cache 假面提供了一種方便簡潔的方式來訪問 Laravel 底層緩存契約的實現(xiàn)。

例如,讓我們引入 Cache 假面到控制器:

<?php

namespace App\Http\Controllers;

use Cache;

class UserController extends Controller 
{
  /**
   * Show a list of all users of the application.
   *
   * @return Response
   */
   public function index()
   {
     $value = Cache::get('key');

     //
   }
}

訪問多種緩存存儲

你可以通過 Cache 假面的 store 方法來訪問多種緩存存儲。傳遞到 store 方法的 key 應(yīng)該與你的 cache 配置文件中的 stores 配置項的列表之一相匹配:

$value = Cache::store('file')->get('foo');

Cache::store('redis')->put('bar', 'baz', 10);

獲取緩存項

你可以通過使用 Cache 假面的 get 方法來從緩存中獲取相關(guān)項的值。如果該項在緩存中并不存在,則返回 null 。如果你需要,你也可以傳遞第二個參數(shù)到 get 方法,這個參數(shù)所傳遞的值會在緩存中項不存在時被返回:

$value = Cache::get('key');

$value = Cache::get('key', 'default');

你甚至可以傳遞 Closure 作為默認(rèn)值。如果緩存的項不存在,Closure 所返回的值將被做為默認(rèn)值。傳遞閉包的方式可以使你從數(shù)據(jù)庫或者其他外部服務(wù)中延遲獲取默認(rèn)值:

$value = Cache::get('key', function () {
  return DB::table(...)->get(); 
});

檢查項是否存在

你可以使用 has 方法來檢查緩存中是否存在該項:

if (Cache::has('key')) {
  //
}

遞增/遞減項中的值

你可以使用 incrementdecrement 方法來調(diào)整緩存項目中的整型值。這兩個方法都可以接受一個數(shù)組作為第二個參數(shù)來進(jìn)行相應(yīng)的數(shù)值調(diào)整:

Cache::increment('key');

Cache::increment('key', $amount);

Cache::decrement('key');

Cache::decrement('key', $amount);

檢索或更新緩存中的項

有時候,你可能希望從緩存中檢索出一個項目,但是當(dāng)該項不存在的時候,你也想存儲一個默認(rèn)值到該項。比如,你希望從緩存中檢索出一個用戶。但是他并不存在,所以你需要從數(shù)據(jù)庫中獲取到他,然后添加到緩存中。你可以使用 Cache::remember 方法來做到這些:

$value = Cache::remember('users', $minutes, function () {
  return DB::table('users')->get(); 
});

如果緩存中沒有檢索到該項,傳遞到 remeber 方法中的閉包將會被執(zhí)行并且其執(zhí)行結(jié)果將會在緩存中進(jìn)行替換。

你也可以合并 rememberforever 方法:

$value = Cache::rememberForever('users', function () {
  return DB::table('users')->get(); 
});

檢索并刪除

如果你需要檢索一個項目,并在檢索到的同時從緩存中刪除該項,你可以使用 pull 方法。就像 get 方法一樣,如果未檢索到該項,將會返回 null :

$value = Cache::pull('key');

存儲項目到緩存

你可以使用 Cache 假面的 put 方法來存儲項目到緩存中。當(dāng)你存儲一個項到緩存中時,你需要指定一個該項需要被緩存的分鐘值:

Cache::put('key', 'value', $minutes);

除了傳遞一個數(shù)值作為緩存過期的分鐘值,你也可以通過傳遞一個 PHP DateTime 實例來設(shè)置緩存的失效時間:

$expiresAt = Carbon::now()->addMinutes(10);

Cache::put('key', 'value', $expiresAt);

add 方法只會在相應(yīng)的項在緩存中不存在時才會被添加進(jìn)緩存。該方法會在項目被添加到緩存后返回 true。否則返回 false

Cache::add('key', 'value', $minutes);

forever 方法可以用來將項目永久的添加進(jìn)緩存。該值只有手動的使用 forget 方法才能被移除:

Cache::forever('key', 'value');

從緩存中移除項目

你可以使用 Cache 假面的 forget 方法來從緩存中移除某項:

Cache::forget('key');

你可以使用 flush 方法來擦除所有的緩存:

Cache::flush();

擦除緩存并不會根據(jù)前綴來進(jìn)行智能擦除,它會移除所有的緩存。所以如果你的應(yīng)用和其他的應(yīng)用共享緩存,你應(yīng)該謹(jǐn)慎的使用該方法。

緩存標(biāo)簽

注意: 緩存標(biāo)簽并不支持 file 或者 database 緩存驅(qū)動。另外,對于將多種標(biāo)簽標(biāo)記為永久存儲的驅(qū)動,性能最好的是能夠提供自動清除過期記錄的驅(qū)動,比如 memcached

存儲標(biāo)記了的項目到緩存

緩存標(biāo)簽允許你將相關(guān)的項目進(jìn)行關(guān)聯(lián)標(biāo)記。并且允許一次性清除所有給定標(biāo)簽的緩存項。你可以通過有序的標(biāo)簽數(shù)組來訪問被標(biāo)記的緩存項目。比如,讓我們訪問被標(biāo)記的項目并使用 put 方法來設(shè)置緩存值:

Cache::tags(['people', 'artists'])->put('John', $john, $minutes);

Cache::tags(['people', 'authors'])->put('Anne', $anne, $minutes);

事實上,你并沒有被限制只使用 put 方法。你可以在標(biāo)簽中使用任意的緩存存儲方法。

訪問被標(biāo)記的緩存項

為了訪問被標(biāo)記了的緩存項,你需要傳遞相應(yīng)的有序列表到 tags 方法:

$john = Cache::tags(['people', 'artists'])->get('John');

$anne = Cache::tags(['people', 'authors'])->get('Anne');

你可以一次性的擦除分配的標(biāo)記或者標(biāo)記列表中的所有項。比如,你可以使用 flush 方法來刪除所有的 peopleauthors 標(biāo)簽和兩者組成的有序列標(biāo)簽里的所有緩存項。所以,AnneJohn 都會被從緩存中移除:

Cache::tags(['people', 'authors'])->flush();

下面的語句將會作為上面語句的對照,將只會從緩存中刪除 authors 標(biāo)簽的項目,所以 Anne 會被刪除,而 John 被保留:

Cache::tags('authors')->flush();

添加自定義的緩存驅(qū)動

為了在自定義的緩存驅(qū)動中繼承 laravel 的緩存。我們需要使用 Cache 假面的 extend 方法,該方法被用來綁定自定義緩存到底層管理中。通常這些都是在服務(wù)提供者中完成。

比如,注冊一個新的緩存驅(qū)動并命名為 '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 方法中的參數(shù)應(yīng)該是驅(qū)動的名稱。這個名稱應(yīng)該和你的 config/cache.php 配置文件中的 driver 選項一致。而第二個參數(shù)是一個閉包,該閉包應(yīng)該返回一個 Illuminate\Cache\Repository 的實現(xiàn)。在閉包中將會被傳遞一個 $app 實例,這個實例是 laravel 中的服務(wù)容器的實例。

Cache::extend 方法的調(diào)用應(yīng)該在 App\Providers\AppServiceProviderboot 方法中完成。或者你可以創(chuàng)建自己的服務(wù)提供者來存儲這個擴(kuò)展。但是不要忘記在 config/app.php 文件中進(jìn)行注冊。

為了創(chuàng)建我們自己的緩存驅(qū)動,我們首先需要實現(xiàn) Illuminate\Constracts\Cache\Store 契約的接口。所以,我們的 MongoDB 緩存實現(xiàn)應(yīng)該看起來像這樣:

<?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 連接來實現(xiàn)這些方法。一旦我們的實現(xiàn)完成,我們就可以完成自己的緩存驅(qū)動的注冊:

Cache::extend('mongo', function ($app) {
  return Cache::repository(new MongoStore); 
});

然后在 config/cache.php 配置文件中更新驅(qū)動為的名稱 driver 為你的擴(kuò)展的名稱。

如果你在為自定義的緩存文件應(yīng)該存放在哪里而疑惑,你可以考慮將其發(fā)布到 Packagist!或者,你可以在 app 目錄中創(chuàng)建一個 Extensions 命名空間。事實上,你應(yīng)該謹(jǐn)記,laravel 并不死板的限制你的目錄結(jié)構(gòu),你應(yīng)該可以根據(jù)自己的習(xí)慣自由的管理你的應(yīng)用目錄結(jié)構(gòu)。

事件

如果你想在任何緩存被操作時執(zhí)行額外的代碼,你可能需要監(jiān)聽緩存的觸發(fā)事件。通常的你應(yīng)該存放這些事件監(jiān)聽器到你的 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',
  ],
 ];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,185評論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,656評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,446評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,951評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,189評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,718評論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,800評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,420評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,755評論 2 371

推薦閱讀更多精彩內(nèi)容

  • 1、配置 Laravel 為不同的緩存系統(tǒng)提供了統(tǒng)一的 API。緩存配置位于 config/cache.php。在...
    layjoy閱讀 956評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • 原文鏈接 必備品 文檔:Documentation API:API Reference 視頻:Laracasts ...
    layjoy閱讀 8,617評論 0 121
  • 測試 簡介 測試是 Laravel 構(gòu)建的核心理念。事實上,Laravel 開箱即用的支持 PHPUnit 測試,...
    Dearmadman閱讀 8,081評論 2 28
  • 簡介 laravel 使實施認(rèn)證的變得非常簡單,事實上,它提供了非常全面的配置項以適應(yīng)應(yīng)用的業(yè)務(wù)。認(rèn)證的配置文件存...
    Dearmadman閱讀 6,151評論 2 13