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

在 Laravel 的 Model 层做数据缓存

时间:2023-03-30 02:44:32 PHP

在Laravel的模型层中进行数据缓存但是我将向您展示一种使用动态记录模型的更精细的Laravel模型缓存技术,这是我在RailsCasts上首次学习的技术。使用模型的唯一缓存键,您可以缓存模型(或关联模型)更新时自动更新(和缓存失效)的模型上的属性和关联,一个好处是访问缓存数据比缓存数据高效得多在控制器中的可重用性,因为它在模型上而不是在单独的控制器方法中。这是该技术的要点:假设您有很多评论文章模型,给定以下Laravel刀片模板,您可以在访问/article/:id路由时获取评论数量,如下所示:

$article->comments->count(){{str_plural('Comment',$article->comments->count())

控制器中可以缓存评论的计数,但是当你有多个查询和数据时一下子,控制器会变得非常臃肿和丑陋。使用控制器,访问缓存数据也不是很方便。我们可以构建一个只在文章更新时才命中数据库的模板,所有访问该模型的代码都可以获得缓存值:

$article->cached_comments_count{{)

通过使用模型访问器,我们可以缓存基于上次更新的评论计数值。那么,我们如何在添加或删除评论时更新文章的updated_at列值呢?先进入touch方法看看。模型的触发器可以通过模型的touch()方法更新文章的updated_at列值:$phpartisantinker>>>$article=\App\Article::first();=>App\Article{#746id:1,title:"HelloWorld",body:"TheBody",created_at:"2018-01-1105:16:51",updated_at:"2018-01-1105:51:07",}>>>$article->updated_at->timestamp=>1515649867>>>$article->touch();=>true>>>$article->updated_at->timestamp=>1515650910我们可以使缓存无效更新的时间戳值。但是在添加或删除评论时,如何触发修改文章的updated_at字段呢?Eloquent模型恰好有一个名为$touches的属性。下面是我们的评论模型的样子:受保护的$touches=['文章'];publicfunctionarticle(){return$this->belongsTo(Article::class);}}}这里的$touches属性是一个数组,里面包含了创建、保存、删除评论时会“触发”的关联信息。缓存属性让我们先回到$article->cached_comments_count访问器。这个方法的实现在App\Article模型中可能看起来像这样:>comments->count();});}我们使用唯一键的cacheKey()方法将模型缓存15分钟,然后在闭包方法中简单地返回评论计数值。注意,我们还使用了Cache::rememberForever()方法,依靠缓存机制的垃圾回收策略来删除过期键值。我设置了一个计时器,以便在缓存刷新之间每隔15分钟,缓存在大部分时间内具有最高的命中率。cacheKey()方法使用模型的唯一键值,当模型更新时对应的缓存失效。下面是我的cacheKey实现代码:publicfunctioncacheKey(){returnsprintf("%s/%s-%s",$this->getTable(),$this->getKey(),$this->updated_at->timestamp);}模型的cacheKey()方法示例输出可能返回如下字符串信息:articles/1-1515650910该键值由表名、模型id值和当前updated_at的时间戳值组成。一旦我们触发了这个模型,时间戳值就会更新,我们的模型缓存也会相应地失效。下面是文章模型的完整代码:getTable(),$this->getKey(),$this->updated_at->timestamp);}publicfunctioncomments(){return$this->hasMany(Comment::class);}publicfunctiongetCachedCommentsCountAttribute(){returnCache::remember($this->cacheKey().':comments_count',15,function(){return$this->comments->count();});}}然后是关联的评论模型:belongsTo(Article::class);}}}接下来做什么?我已经我已经向您展示了如何缓存一个简单的评论计数,但是您如何缓存所有评论呢?publicfunctiongetCachedCommentsAttribute(){returnCache::remember($this->cacheKey().':comments',15,function(){return$this->comments;});}也可以选择转换注释到一个数组而不是序列化模型,只允许简单的数组访问前端的数据:publicfunctiongetCachedCommentsAttribute(){returnCache::remember($this->cacheKey().':comments',15,function(){return$this->comments->toArray();});}最后,我在Article模型中定义了cacheKey()方法,但是你可能想通过一个名为ProvidesModelCacheKey的特征来定义这个方法,这样你就可以在复合模型中使用它或定义所有模型在基本模型中扩展的方法。您甚至可能想将它用于实现cacheKey()方法的模型。使用合同(接口)。我希望你发现这个简单的技巧很有用!