摘要:說明本文主要學習下的模型觀察者,把一點點經(jīng)驗分享出來希望對別人能有幫助。模型觀察者這個功能能做很多事情,比如模型更新時發(fā)個通知。總結本篇文章主要學了下的模型觀察者,發(fā)現(xiàn)這個功能也能使代碼結構更清晰,覺得挺好的。
說明:本文主要學習下Laravel的Model Observer模型觀察者,把一點點經(jīng)驗分享出來希望對別人能有幫助。同時,作者會將開發(fā)過程中的一些截圖和代碼黏上去,提高閱讀效率。
備注:上一篇文章:Laravel學習筆記之Redis保存頁面瀏覽量,作者在開發(fā)的時候有個邏輯有點在意:那篇文章再用Redis保存瀏覽量后,當瀏覽量達到設置的次數(shù)后刷到MySQL里,同時把Redis里該瀏覽量鍵抹掉,還有Post的內容鍵抹掉,以便下一次請求從MySQL里請求到新的數(shù)據(jù)并緩存。研究時,發(fā)現(xiàn)可以使用Model Observer來實現(xiàn)Model的事件變化來自動刷新flush下Redis,個人覺得有點像是定義了一個事件監(jiān)聽器監(jiān)聽模型事件一樣。這篇文章就用下Model Observer重新組織下代碼。可以大概看下上篇文章的基本邏輯。
開發(fā)環(huán)境:Laravel5.1+MAMP+PHP7+MySQL5.5
沒有Model Observer邏輯看下最主要的瀏覽量達到一定量后刷到MySQL里的邏輯:
/** * 不同用戶訪問,更新緩存中瀏覽次數(shù) * @param $id * @param $ip */ public function updateCacheViewCount($id, $ip) { $cacheKey = "post:view:".$id; //這里以Redis哈希類型存儲鍵,就和數(shù)組類似,$cacheKey就類似數(shù)組名,$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的瀏覽量鍵抹掉,等著下一次請求重新開始計數(shù) 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還是緩存的舊數(shù)據(jù),極端情況300秒內都是舊數(shù)據(jù),而緩存里已經(jīng)有了29個新增訪問量 //實際上也可以這樣做:在緩存post的時候,可以把view_count多帶帶拿出來存入鍵值里如single_view_count,每一次都是給這個值加1,然后把這個值傳入視圖里 //或者平衡設置下postViewLimit和ipExpireSec這兩個參數(shù),對于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,和數(shù)組類似,就像$cacheKey[$ip] = 1; Redis::command("HSET", [$cacheKey, $ip, "1"]); } }
這里在瀏覽量達到self::postViewLimit后把view_count刷到MySQL里并刷新下Redis,使用這個邏輯:
Redis::command("DEL", ["laravel:post:cache:".$id]);有Model Observer邏輯
可以注冊一個模型觀察者,在觀察者類里做一些模型對應事件的邏輯,這里就是刷掉一些緩存鍵值。
在app/Observers/PostObserver.php(模型觀察類放在哪里可以自定義)里:
flush(); } public function saving() { } public function deleted() { } }
這里使用flush()方法只刷指定tag的緩存鍵,免得把別的key也刷了。這里打的標簽其實是:["posts", "model"],Post::table()定義返回Model關聯(lián)的表名,看下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關聯(lián)的表 * @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,則從數(shù)據(jù)庫中取值,并存入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(); //觸發(fā)瀏覽量計數(shù)器事件 event(new PostViewCount($post, $ip)); return view("browse.post", compact("post")); }
現(xiàn)在測試下當view_count被刷進MySQL時,即saved()事件后,模型觀察類有沒有把["posts", "model"]這個標簽的鍵給刷掉。這里設置下:
class PostEventListener { /** * 同一post最大訪問次數(shù),再刷新數(shù)據(jù)庫 */ const postViewLimit = 3; ... }
不同IP刷下3次后緩存的Post Model有沒有被刷掉。
第一個IP訪問時Post Model已經(jīng)被刷到Redis里了:
第三個IP訪問時,Post Model已經(jīng)被從Redis里刷掉了:
it is working!!!
這證明了view_count被save()進MySQL時,模型觀察類邏輯起作用了。當然第四個IP訪問后頁面就會顯示最新的瀏覽量了。
模型觀察者這個功能能做很多事情,比如Model Update模型更新時發(fā)個通知。或者就像一篇文章的內容重新編輯保存后,把原來緩存內的該篇文章內容刷新下,這樣下一個請求來的時候讀的就是最新的文章內容了。作者以后會繼續(xù)研究研究,發(fā)現(xiàn)挺好玩的東西到時候分享出來吧。
總結:本篇文章主要學了下Laravel的Model Observer模型觀察者,發(fā)現(xiàn)這個功能也能使代碼結構更清晰,覺得挺好的。最近一直在瞎研究,有遇到好玩的再分享出來吧。
歡迎關注Laravel-China。
RightCapital招聘Laravel DevOps
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/21686.html
摘要:模型事件在的世界中你對大多數(shù)操作都會或多或少的觸發(fā)一些模型事件今天就來看一下模型事件的使用。事先已經(jīng)定義好了個模型事件以供我們使用它們分別是。和會在數(shù)據(jù)庫中的真值修改前后觸發(fā)。監(jiān)聽數(shù)據(jù)即將保存的事件。監(jiān)聽數(shù)據(jù)從軟刪除狀態(tài)恢復后的事件。 模型事件 在 Laravel 的世界中,你對 Eloquent 大多數(shù)操作都會或多或少的觸發(fā)一些模型事件,今天就來看一下模型事件的使用。 Laravel...
摘要:模式定義觀察者模式定義對象間的一種一對多依賴關系,使得每當一個對象狀態(tài)發(fā)生改變時,其相關依賴對象皆得到通知并被自動更新。 觀察者模式 Laravel的Event事件系統(tǒng)提供了一個簡單的觀察者模式實現(xiàn),能夠訂閱和監(jiān)聽應用中發(fā)生的各種事件,在PHP的標準庫(SPL)里甚至提供了三個接口SplSubject, SplObserver, SplObjectStorage來讓開發(fā)者更容易地實現(xiàn)觀...
摘要:說明本文主要講述使用作為緩存加快頁面訪問速度。何不用來做緩存,等到該達到一定瀏覽頁面后再刷新下,效率也很高。可作緩存系統(tǒng)隊列系統(tǒng)。 說明:本文主要講述使用Redis作為緩存加快頁面訪問速度。同時,作者會將開發(fā)過程中的一些截圖和代碼黏上去,提高閱讀效率。 備注:作者最近在學習github上別人的源碼時,發(fā)現(xiàn)好多在計算一篇博客頁面訪問量view_count時都是這么做的:利用Laravel...
摘要:抱歉,最近忙,本篇等有時間更新。引言本文基于框架做的一個生成和存儲,主要目的是學習使用框架。書籍基于的,學習時使用框架開發(fā)。開發(fā)環(huán)境備注一直想把這本書的個作為系列分享出來,供初學者學習玩玩。 抱歉,最近忙,本篇等有時間更新。 引言 本文基于Laravel框架做的一個URL生成和存儲demo,主要目的是學習使用Laravel框架。內容基于英文書籍《Packt.Laravel.Applic...
閱讀 1022·2021-11-25 09:43
閱讀 1680·2019-08-30 13:59
閱讀 1615·2019-08-30 11:22
閱讀 2139·2019-08-30 11:06
閱讀 1309·2019-08-28 17:51
閱讀 3745·2019-08-26 12:12
閱讀 790·2019-08-26 12:11
閱讀 458·2019-08-26 12:10