Laravel之Model Observer模型

本文主要學習下Laravel的Model Observer模型觀察者,小編把自己的一點點經驗分享出來希望對別人能有幫助。同時,作者會將開發過程中的一些截圖和代碼黏上去,提高閱讀效率。

開發環境:Laravel5.1+MAMP+PHP7+MySQL5.5

沒有Model Observer邏輯

看下最主要的瀏覽量達到一定量後刷到MySQL裡的邏輯:

代碼如下

/**

* 不同用戶訪問,更新緩存中瀏覽次數

* @param $id

* @param $ip

*/

public function updateCacheViewCount($id, $ip)

{

$cacheKey = 'post:view:'.$id;

//這裡以Redis哈希類型存儲鍵,就和數組類似,$cacheKey就類似數組名,$ip為$key.HEXISTS指令判斷$key是否存在$cacheKey中

if(Redis::command('HEXISTS', [$cacheKey, $ip])){

//哈希類型指令HINCRBY,就是給$cacheKey[$ip]加上一個值,這裡一次訪問就是1

$incre_count = Redis::command('HINCRBY', [$cacheKey, $ip, 1]);

//redis中這個存儲瀏覽量的值達到30後,就往MySQL裡刷下,這樣就不需要每一次瀏覽,來一次query,效率不高

if($incre_count == self::postViewLimit){

$this->updateModelViewCount($id, $incre_count);

//本篇post,redis中瀏覽量刷進MySQL後,把該篇post的瀏覽量鍵抹掉,等著下一次請求重新開始計數

Redis::command('HDEL', [$cacheKey, $ip]);//瀏覽量這個刪除key操作也可以在Model Observer裡做,不過要把Redis改成Cache的方法,這裡就不寫了

//同時,抹掉post內容的緩存鍵,這樣就不用等10分鐘後再更新view_count了,

//如該篇post在100秒內就達到了30訪問量,就在3分鐘時更新下MySQL,並把緩存抹掉,下一次請求就從MySQL中請求到最新的view_count,

//當然,100秒內view_count還是緩存的舊數據,極端情況300秒內都是舊數據,而緩存裡已經有了29個新增訪問量

//實際上也可以這樣做:在緩存post的時候,可以把view_count單獨拿出來存入鍵值裡如single_view_count,每一次都是給這個值加1,然後把這個值傳入視圖裡

//或者平衡設置下postViewLimit和ipExpireSec這兩個參數,對於view_count這種實時性要求不高的可以這樣做來著

//加上laravel前綴,因為Cache::remember會自動在每一個key前加上laravel前綴,可以看cache.php中這個字段:'prefix' => 'laravel'

//使用Model Observer後註銷這句

// Redis::command('DEL', ['laravel:post:cache:'.$id]);//利用Model Observer,這裡就不用刷掉這個key,邏輯可在模型觀察器裡做

}

}else{

//哈希類型指令HSET,和數組類似,就像$cacheKey[$ip] = 1;

Redis::command('HSET', [$cacheKey, $ip, '1']);

}

}

這裡在瀏覽量達到self::postViewLimit後把view_count刷到MySQL裡並刷新下Redis,使用這個邏輯:

代碼如下

Redis::command('DEL', ['laravel:post:cache:'.$id]);

「php框架實例」| Laravel之Model Observer模型

有Model Observer邏輯

可以註冊一個模型觀察者,在觀察者類裡做一些模型對應事件的邏輯,這裡就是刷掉一些緩存鍵值。

在app/Observers/PostObserver.php(模型觀察類放在哪裡可以自定義)裡:

代碼如下

/**

* Created by PhpStorm.

* User: liuxiang

* Date: 16/6/19

* Time: 17:11

*/

namespace App\\Observers;

use App\\Post;

use Cache;

class PostObserver

{

public function saved()

{

//原來邏輯是:view_count達到30次後,把view_count刷進MySQL裡,同時刪掉緩存在Redis裡的$post整個模型的內容.

//這裡觀察saved事件,當把save_count值save()進MySQL後,就在這裡刷下redis這個post的key.

//在把內容緩存進Redis裡,加上tag標籤以便於識別和分別操作,個人覺得這是一個好習慣.

Cache::tags([Post::table(), 'model'])->flush();

}

public function saving()

{

}

public function deleted()

{

}

}

這裡使用flush()方法只刷指定tag的緩存鍵,免得把別的key也刷了。這裡打的標籤其實是:['posts', 'model'],Post::table()定義返回Model關聯的表名,看下Post這個Model:

代碼如下

class Post extends Model

{

public function category()

{

return $this->belongsTo(Category::class);

}

public function comments()

{

return $this->hasMany(Comment::class);

}

public function tags()

{

return $this->belongsToMany(Tag::class)->withTimestamps();

}

/**

* 在boot()方法裡註冊下模型觀察類

* boot()和observe()方法都是從Model類繼承來的

* 主要是observe()來註冊模型觀察類,可以用Post::observe(new PostObserve())

* 並放在代碼邏輯其他地方如路由都行,這裡放在這個Post Model的boot()方法裡自啟動。

*/

public static function boot()

{

parent::boot(); // TODO: Change the autogenerated stub

static::observe(new PostObserver());

}

/**

* 返回該Model關聯的表

* @return string

*/

public static function table()

{

$model = new static;

//調用Model類的public function getTable()

return $model->getTable();

}

}

還有別忘了在PostController裡緩存Post Model的時候打上標籤:

代碼如下

public function showPostCache(Request $request, $id)

{

//Redis緩存中沒有該post,則從數據庫中取值,並存入Redis中,該鍵值key='post:cache'.$id生命時間10分鐘

//在把內容緩存進Redis裡,加上tag標籤以便於識別和分別操作,個人覺得這是一個好習慣實際上.這裡加個該post對應的表名標籤,保持唯一性

$post = Cache::tags([Post::table(), 'model'])->remember('post:cache:'.$id, self::modelCacheExpires, function () use ($id) {

return Post::whereId($id)->first();

});

//獲取客戶端IP

$ip = $request->ip();

//觸發瀏覽量計數器事件

event(new PostViewCount($post, $ip));

return view('browse.post', compact('post'));

}

現在測試下當view_count被刷進MySQL時,即saved()事件後,模型觀察類有沒有把['posts', 'model']這個標籤的鍵給刷掉。這裡設置下:

class PostEventListener

{

/**

* 同一post最大訪問次數,再刷新數據庫

*/

const postViewLimit = 3;

...

}

不同IP刷下3次後緩存的Post Model有沒有被刷掉。

第一個IP訪問時Post Model已經被刷到Redis裡了:

「php框架實例」| Laravel之Model Observer模型

第三個IP訪問時,Post Model已經被從Redis裡刷掉了:

「php框架實例」| Laravel之Model Observer模型

it is working!!!

這證明了view_count被save()進MySQL時,模型觀察類邏輯起作用了。當然第四個IP訪問後頁面就會顯示最新的瀏覽量了。

「php框架實例」| Laravel之Model Observer模型

模型觀察者這個功能能做很多事情,比如Model Update模型更新時發個通知。或者就像一篇文章的內容重新編輯保存後,把原來緩存內的該篇文章內容刷新下,這樣下一個請求來的時候讀的就是最新的文章內容了。作者以後會繼續研究研究,發現挺好玩的東西到時候分享出來吧。

總結:本次主要學了下Laravel的Model Observer模型觀察者,發現這個功能也能使代碼結構更清晰,覺得挺好的。最近一直在瞎研究,有遇到好玩的再分享出來吧。

PHP網站開發教程,php學習大本營的集合地。早關注,早學習,早提升!(搜索公眾號名稱:PHP網站開發教程 可以關注我們哦!)


分享到:


相關文章: