<h3>$article->comments->count() {{ str_plural('Comment', $article->comments->count())</h3>@H_419_4@您可以在控制器中缓存评论的计数,但是当您有多个需要缓存的一次性查询和数据时,控制器会变得非常臃肿难看。使用控制器,访问缓存的数据也不是很方便。@H_419_4@我们可以构建一个模板,它仅在文章更新时访问数据库,并且访问该模型的所有代码都可以获取缓存值:
<h3>$article->cached_comments_count {{ str_plural('Comment', $article->cached_comments_count)</h3>@H_419_4@通过使用模型访问器,我们可以缓存基于最后一次文章更新的评论计数值。@H_419_4@因此,在评论新增或删除时我们该怎么更新文章的 updated_at 列值呢?@H_419_4@先进入 touch 方法看看。@H_419_4@模型的触发@H_419_4@可以通过使用模型的 touch() 方法来更新文章的 updated_at 列值:@H_419_4@$ PHP artisan tinker
>>> $article = \App\Article::first();=> App\Article {#746 ID: 1, Title: "Hello World", body: "The Body", created_at: "2018-01-11 05:16:51", updated_at: "2018-01-11 05:51:07", }>>> $article->updated_at->timestamp=> 1515649867>>> $article->touch();=> true>>> $article->updated_at->timestamp=> 1515650910@H_419_4@我们可以用更新的 timestamp 值使缓存失效。不过在新增或删除一个评论时,我们怎么触发修改文章的 updated_at 字段呢?@H_419_4@碰巧 Eloquent 模型中有一个属性就叫 $touches 。下面是我们的评论模型的大概样子:
<?PHPnamespace App;use App\Article;use Illuminate\Database\Eloquent\Model;class Comment extends Model{ protected $guarded = []; protected $touches = ['article']; public function article() { return $this->belongsTo(Article::class); }}@H_419_4@这里的 $touches 属性是个数组,包含了在评论的创建、保存和删除时会引起 “触发” 的关联信息。@H_419_4@缓存的属性@H_419_4@我们先回到 $article->cached_comments_count 访问器。该方法的实现可能象 App\Article 模型中的样子:
public function getCachedCommentsCountAttribute(){ return Cache::remember($this->cacheKey() . ':comments_count', 15, function () { return $this->comments->count(); });}@H_419_4@我们使用唯一键值的 cacheKey() 方法缓存模型 15 分钟,然后简单地在闭包方法中返回评论计数值。@H_419_4@注意,我们也用到了 Cache::rememberForever() 方法,靠着缓存机制的垃圾回收策略以删除过期的键值。我设置了一个定时器,以便在每隔 15 分钟的缓存刷新间隔里,缓存可在该时间的多数范围内有最高的命中率。@H_419_4@cacheKey() 方法要用到模型的唯一键值,并且在模型更新时对应缓存失效。下面是我的 cacheKey 实现代码:
public function cacheKey(){ return sprintf( "%s/%s-%s", $this->gettable(), $this->getKey(), $this->updated_at->timestamp );}@H_419_4@模型的 cacheKey() 方法示例输出结果可能返回下面的字串信息:
articles/1-1515650910@H_419_4@这个键值是由表名、模型 ID 值及当前 updated_at 的 timestamp 值组成。一旦我们触发这个模型,timestamp 值就会更新,并且我们的模型缓存就会相应地失效。@H_419_4@以下是 Article 模型的完整代码:
<?PHPnamespace App;use App\Comment;use Illuminate\Support\Facades\Cache;use Illuminate\Database\Eloquent\Model;class Article extends Model{ public function cacheKey() { return sprintf( "%s/%s-%s", $this->gettable(), $this->getKey(), $this->updated_at->timestamp ); } public function comments() { return $this->hasMany(Comment::class); } public function getCachedCommentsCountAttribute() { return Cache::remember($this->cacheKey() . ':comments_count', 15, function () { return $this->comments->count(); }); }}@H_419_4@然后是关联的 Comment 模型:
<?PHPnamespace App;use App\Article;use Illuminate\Database\Eloquent\Model;class Comment extends Model{ protected $guarded = []; protected $touches = ['article']; public function article() { return $this->belongsTo(Article::class); }}@H_419_4@接下来做什么?@H_419_4@我已经向你展示了如何缓存一个简单的评论计数,但是如何缓存所有的评论呢?
public function getCachedCommentsAttribute(){ return Cache::remember($this->cacheKey() . ':comments', 15, function () { return $this->comments; });}@H_419_4@你也可以选择将评论转换为数组替代序列化模型,只允许在前端对数据进行简单的数组访问:
public function getCachedCommentsAttribute(){ return Cache::remember($this->cacheKey() . ':comments', 15, function () { return $this->comments->toArray(); });}@H_419_4@最后, 我在 Article 模型中定义了 cacheKey() 方法,但是你可能想要通过一个名为 ProvIDesModelCacheKey 的 trait 来定义这个方法以便你可以在复合模型中使用或者在一个基础模型中定义所有模型扩展的方法。 你甚至可能想要为实现 cacheKey() 方法的模型使用使用契约 (接口)。@H_419_4@推荐教程:《PHP教程》《Laravel》 总结
以上是内存溢出为你收集整理的在 Laravel 中如何在 Model 层进行数据缓存?全部内容,希望文章能够帮你解决在 Laravel 中如何在 Model 层进行数据缓存?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)