当前位置: 首页 > 后端技术 > PHP

LaravelORM缓存Model--find方法

时间:2023-03-30 05:11:29 PHP

前段时间做项目的时候,想缓存Model::find方法,不改变方法签名。并希望即插即用。1.首先看一下我们调用find方法时框架做了什么?找到Illuminate\Database\Eloquent\Model的代码,搜索找到,没有这个方法。似乎__callStatic魔术方法不见了。这个方法只有一行代码:return(newstatic)->$method(...$parameters);static是指调用静态方法的类(如果使用UserModel::find(1),那么static就是代表UserModel类)。好像实例化了一个对象,调用了一个成员方法。2、分析如何优雅地把一只脚插在中间。为了在调用find的时候能够先到我们的缓存,我们需要重写__callStatic方法,检测如果是find方法,会先返回缓存中的数据。另外,为了达到即插即用的效果,我们使用继承来代替Trait。核心逻辑如下:publicstaticfunctioncreate($data=null){if($data==null){returnnull;}$实例=新静态;foreach($dataas$key=>$value){$instance[$key]=$value;}return$instance;}/***如果方法是find($id,$nocache)**@paramstring$method*@paramarray$parameters*@returnmixed*/publicstaticfunction__callStatic($method,$parameters){if($method=='find'){//从缓存中获取数据$obj=static::create(json_decode(Redis::get(static::getCacheKey($parameters[0])),true));if(null==$obj){$obj=(newstatic)->$method(...$parameters);如果(null==$obj){返回null;}else{$key=static::getCacheKey($parameters[0]);//设置缓存和过期时间Redis::set($key,$obj);Redis::expire($key,static::$expire_time);返回$对象;}}else{$obj->;存在=真;返回$对象;}}elseif($method=='findNoCache'){$method='find';返回(新静态)->$方法(...$参数);}return(newstatic)->$method(...$parameters);}私有静态函数getCacheKey($id){$name=str_replace('\\',':',__CLASS__);return"{$name}:{$id}";}上面已经介绍了大致的逻辑:重写__callStatic方法,判断如果调用了find,则去缓存(没有缓存,需要设置缓存在查询之后)并添加findNoCache方法。3、细节补充当修改(或删除)数据(调用save方法)时,需要删除缓存的内容。privatestaticfunctionclearCache($id){Redis::del(self::getCacheKey($id));}/***保存时清除缓存*@paramarray$options*/publicfunctionsave(array$options=[]){static::clearCache($this[$this->primaryKey]);returnparent::save($options);}//delete方法是我临时写的,内容和save方法的使用方法差不多。在需要使用查找缓存的Model类中,增加一行就可以了。classUserextendsBaseModel{useMemoryCacheTrait;}去试试吧。