CakePHP 3.x:缓存分页搜索

SRw*_*ebs 1 pagination caching cakephp cakephp-3.0

我需要在CakePHP 3分页搜索中缓存分页结果.

当我使用CakePHP 2.x时,我能够在appModel中覆盖paginate函数.使用新的CakePHP ORM可以获得相同的结果吗?因为$query->cache()在paginate查询对象中不起作用.

我已经阅读了关于这个主题的一些讨论,但如果可能的话我需要一个例子.

AD7*_*six 5

分页查询

问题中没有显示代码,但我们假设您从一个简单的烘焙控制器索引操作开始:

public function index()
{   
    $this->set('posts', $this->paginate($this->Posts));
    $this->set('_serialize', ['posts']);
}
Run Code Online (Sandbox Code Playgroud)

首先,要认识到控制器方法paginate 接受表或查询对象 - 如果传递了表对象,则paginator组件只需调用find来处理查询对象.所以,上面的代码在功能上等同于:

public function index()
{   
    $query = $this->Posts->find();

    $this->set('posts', $this->paginate($query));
    $this->set('_serialize', ['posts']);
}
Run Code Online (Sandbox Code Playgroud)

使用查询缓存方法

只需对上面的代码进行一些小修改就可以使用查询的缓存方法:

public function index()
{
    $query = $this->Posts->find();

    $cacheKey = $this->name . '_' . md5(json_encode($this->request->query));
    $query->cache($cacheKey);

    $this->set('posts', $this->paginate($query));
    $this->set('_serialize', ['posts']);
}
Run Code Online (Sandbox Code Playgroud)

查询参数和控制器名称用于生成唯一的缓存键,以便一次调用paginate的缓存结果不会与另一个请求的调用混淆.

照顾好计数

当以这种方式使用时仍将发出计数,如果这是一个问题,它仍然可以通过定义计数器回调来防止:

public function index()
{
    $query = $this->Posts->find();

    $cacheKey = $this->name . '_' . md5(json_encode($this->request->query));
    $searchTerms = []; // define this
    $countCacheKey = $this->name . '_' . md5(json_encode($searchTerms)) . '_count';

    $query
        ->cache($cacheKey)
        ->counter(function($query) use ($countCacheKey) {
            return Cache::remember($countCacheKey, function()  use ($query) {
                return $query->count();
            }); 
        }); 


    $this->set('posts', $this->paginate($query));
    $this->set('_serialize', ['posts']);
}
Run Code Online (Sandbox Code Playgroud)

即简单地将调用包装到count方法中Cache::remember.

请注意,答案中用于计数的缓存键对于所有请求都是相同的,因为在此示例中要分页的行数对于所有请求都是相同的.如果您要对搜索进行分页 - 例如,搜索条件应该用于计数缓存键.