[英]Laravel cache with route model binding?
我正在向 Laravel 应用程序路由添加缓存。 我有一个在我的网站上呈现博客文章的功能:
public function show(Post $post)
{
SEO::setTitle($post->title);
SEO::setDescription($post->subtitle);
SEO::setCanonical('https://employbl.com/blog/' . $post->slug);
SEO::opengraph()->setUrl('https://employbl.com/blog/' . $post->slug);
SEO::opengraph()->addProperty('type', 'article');
SEO::opengraph()->addImage($post->featured_image);
SEO::twitter()->setSite('@Employbl_Jobs');
$markdown = Markdown::parse($post->body);
return view('blog.post', compact('post', 'markdown'));
}
这是调用方法的Route::get('/blog/{post}', 'PostController@show')->name('posts.show');
: Route::get('/blog/{post}', 'PostController@show')->name('posts.show');
以便我的博客呈现带有 slug 的 URL,例如: https : //employbl.com/blog/laravel-vue-tailwindcss-single-page-application-spa
在此路由上实现缓存以便用户更快地加载页面的最佳方法是什么?
会不会是这样的:
$post = Cache::rememberForever('blog-post' . $post->id, function(){
return $post;
});
或者路由模型绑定甚至需要缓存? 缓存键是否需要唯一,或者我可以只使用“博客文章”作为缓存键吗? 缓存$markdown
变量而不是$post
变量会更好吗? 两个都?
你在这里有几个问题,所以我会试着回答每个问题。 答案可能并不完美,因为我目前无法参考或确认自己的记忆。
如果您尝试缓存视图的最终输出,则可以有效地将最终视图调用替换为:
return Cache::rememberForever('blog-post' . $post->id, function() use ($post) {
// Do your SEO and markdown stuff here
return view('blog.post', compact('post', 'markdown'))->render();
});
帖子的缓存键必须是唯一的。 模型路由系统对缓存系统一无所知,它只是将值传递给控制器的一种方式,控制器根据 URI 对传入数据进行一些假设。 所以你现在所做的一切都很好。
您的问题是我应该缓存帖子、降价还是两者兼而有之? 是它可能不会有什么不同
1) 您正在调用模型 GET 路由。 这具有每次从数据库加载 Post 的效果,使得 Post 本身的缓存无关紧要。 即使缓存渲染视图本身也是如此。
2)您的视图调用需要 Post 本身作为参数 [of compact() ]。 您需要从某处加载它,这意味着再次调用数据库来检索帖子。
3)您正在使用Cache::rememberForever这意味着缓存永远不会过期。 因此,在第一次之后加载 Post 将毫无意义,因为它将永远不会被再次使用(结果将被永久缓存!)。 除非您使缓存无效(这使得rememberForever变得毫无意义),否则以后的编辑(如果有)将不起作用。
因此,对于这种情况,我建议您远离模型路由,而尝试使用传统的基于 id 的路由
public function show(Request $request, $id)
{
return Cache::remember('blog-post'.$id, ttl, function() use($id) {
$post = Post::find($id);
// Do SEO and markdown stuff
return view('blog.post', compact('post', 'markdown'))->render();
});
}
其中ttl是缓存到期的时间。
我希望解决使用路由模型绑定绑定的缓存模型的类似问题,并找到了以下解决方案。
// On the Model class add the following method.
public function resolveRouteBinding($value, $field = null): ?Model
{
return Cache::remember('my.custom.key'.$value, 3600, function () use ($value) {
return $this->where('slug', $value)->firstOrFail();
});
}
方法细节可以在这里找到: Customizing Resolution Logic
值得注意的是,您很可能宁愿在没有Cache::remember()
方法的情况下使用它,这样您就不会缓存返回 null 的内容。 最好采用以下方式执行此操作:
// On the Model class add the following method.
public function resolveRouteBinding($value, $field = null): ?Model
{
$cacheName = "my.custom.key.{$value}";
if (Cache::has($cacheName)) {
return Cache::get($cacheName);
}
$result = $this->query('slug', $value)->firstOrFail();
Cache::put($cacheName, $result, 3600);
return $result;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.