下面由laravel開發教程欄目給大家介紹Laravel ORM 中你不知道的騷操作,希望對需要的朋友有所幫助!
前段時間做項目時候,想要在不改變方法簽名的情況下,給 Model::find 方法做個緩存。而且想要做到即插即用。
1.先看一下當我們調用 find 方法時,框架干了什么?
找到 IlluminatedatabaseEloquentModel 的代碼,搜索 find,沒有該方法。看來是走了 __callStatic 這個魔術方法。該方法里只有一行代碼:
return?(new?static)->$method(...$parameters);
static 指的是調用該靜態方法的類(如果使用的是 UserModel::find(1),則 static 就代表 UserModel 類)。看來是實例化了一個對象,并調用了成員方法。
2.分析如何優雅地在中間插一腳
為了能夠在調用 find 時候,先走我們的緩存,所以我們需要覆蓋 __callStatic 方法,并檢測如果是 find 方法,則優先返回緩存中的數據。
另外,為了能夠達到即插即用的效果,我們使用繼承的方式,而是使用了 Trait。核心邏輯如下:
public?static?function?create($data?=?null){ ????if?($data?==?null){ ????????return?null; ????} ????$instance?=?new?static; ????foreach?($data?as?$key?=>?$value){ ????????$instance[$key]?=?$value; ????} ????return?$instance; } /** ?*?如果方法是?find($id,?$nocache) ?* ?*?@param??string??$method ?*?@param??array??$parameters ?*?@return?mixed ?*/ public?static?function?__callStatic($method,?$parameters) { ????if?($method?==?'find'){ ????????//?從緩存中獲取數據 ????????$obj?=?static::create(json_decode(Redis::get(static::getCacheKey($parameters[0])),?true)); ????????if?(null?==?$obj){ ????????????$obj?=?(new?static)->$method(...$parameters); ????????????if?(null?==?$obj){ ????????????????return?null; ????????????}?else?{ ????????????????$key?=?static::getCacheKey($parameters[0]); ????????????????//?設置緩存及過期時間 ????????????????Redis::set($key,?$obj); ????????????????Redis::expire($key,?static::$expire_time); ????????????????return?$obj; ????????????} ????????}?else?{ ????????????$obj->exists?=?true; ????????????return?$obj; ????????} ????}?else?if($method?==?'findNoCache'){ ????????$method?=?'find'; ????????return?(new?static)->$method(...$parameters); ????} ????return?(new?static)->$method(...$parameters); } private?static?function?getCacheKey($id){ ????$name?=?str_replace('',?':',?__CLASS__); ????return?"{$name}:{$id}"; }
大體邏輯上面已經介紹過了:覆蓋 __callStatic 方法,判斷如果是調用 find ,則走緩存(無緩存,查詢后需要設置緩存)。另新增 findNoCache 方法。
3.細節補充
當修改(或刪除)數據(調用 save 方法)時需要刪除已緩存的內容。
private?static?function?clearCache($id){ ????Redis::del(self::getCacheKey($id)); } /** ?*?when?save,?should?clear?cache ?*?@param?array?$options ?*/ public?function?save(array?$options?=?[]){ ????static::clearCache($this[$this->primaryKey]); ????return?parent::save($options); } //?delete?方法我暫時寫,內容類似?save?方法 如何使用。在需要使用?find?緩存的?Model?類里,加上一行就夠了。 class?User?extends?BaseModel { ????use?MemoryCacheTrait; }
快去試試吧。
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END