手机版
你好,游客 登录 注册
背景:
阅读新闻

Laravel 缓存分页结果

[日期:2015-11-02] 来源:zhuzhichao.com  作者:朱智超 [字体: ]

前言

提高页面速度的一个很好用的方法就是使用 Cache 。而在Laravel中Cache的使用和配置也是相当方便,在项目中合理的使用能得到意想不到的效果(当然,使用不当也会造成坏的效果)。

遇见问题

于是,我写下了下面看似非常正常的代码:

$newsList = Cache::remember('newsList'.$uuid, $minutes, function() {
    return News::with('lastReplyUser', 'user')
        ->checked()
        ->recentReply()
        ->paginate(Config::get('page.newsListSize'));
});

刷新页面后的结果让我出乎意料,报错Exception Serialization of 'Closure' is not allowed

Closure_is_not_allowed

分析问题

速速打开xdebug调试,明明返回的是Paginator这个对象。怎么会说无法序列化Closure呢?
Paginator

正如错误提示,这个paginator对象有属性是闭包,所以在序列化的时候无法进行。

在强有力的xdebug的帮助下,我找到了元凶。

终于发现了这个closure属性了

具体赋值位置: /Path/To/Nidexiangmu/vendor/laravel/framework/src/Illuminate/View/Engines/EngineResolver.php 30行这个方法的行为

public function register($engine, Closure $resolver)
    {
        $this->resolvers[$engine] = $resolver;
    }

解决问题

随随便便修改框架源代码,这不是咱能干的事儿。既然这样,那就来个曲线救国吧!对paginator无法缓存,咱们就缓存点别的。

方案1

对查询进行缓存

$newsList = News::with('lastReplyUser', 'user')
    ->checked()
    ->whereNotIn('id', $selectedId)
    ->recentReply()
    ->remember($minutes)   # 注意这一行
    ->paginate(Config::get('page.newsListSize'));
方案2

对paginator需要用到的内容(items和链接)进行缓存

$newsList = Cache::remember('newsList'.$uuid, $minutes, function() {
    $data = News::with('lastReplyUser', 'user')
        ->checked()
        ->recentReply()
        ->paginate(Config::get('page.newsListSize'));

    return ['result' => $data->getItems(), 'links' => (string)$data->links()];
});

总结

注意,方案2中的*links()*这个方法调用后使用了string的强制转换,因为返回的内容是 view 对象,而view对象的属性中有闭包,所以任何时候不要试图序列化(包括缓存操作这种包含序列号的操作)view对象和属性中拥有view对象的数组或对象(这句话好拗口啊,其实就是只有存在view对象,就不要序列化或缓存)。

Ubuntu下使用Nginx部署Laravel  http://www.linuxidc.com/Linux/2015-08/121988.htm

Ubuntu 14.04 上使用 Nginx 部署 Laravel 5.0  http://www.linuxidc.com/Linux/2015-08/121986.htm

本文永久更新链接地址http://www.linuxidc.com/Linux/2015-11/124751.htm

linux
相关资讯       Laravel  Laravel 缓存 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款