我正在尝试缓存查询,条件是在第一次请求之后,如果查询对象不为空,我想缓存。我试过如下
public function getCategories()
{
$categoriesTable = TableRegistry::getTableLocator()->get( 'Categories' );
if(CakeCacheCache::read('categories', 'redis_cache') == null)
{
$categories = $categoriesTable->find();
if(!$categories->isEmpty())
{
print("hello");
$categories->cache('categories','redis_cache');
debug(CakeCacheCache::read('categories', 'redis_cache'));
}
$this->set('categories',$categories);
}else{
$this->set('categories',CakeCacheCache::read('categories', 'redis_cache'));
}
$this->viewBuilder()->setOption('serialize', ['categories']);
}
Output I got in postman
第一次点击
hello
null
第二次点击
hello
null
但是在注释if(!$categories->isEmpty())
条件后
第一次点击
{
"categories": [
{
"id": 2,
...
}
同样,如果我像下面这样写条件,它也能正常工作。
if(!$categoriesTable->find('all')->isEmpty()). // it's working
我在这里做错了什么?
查询是延迟求值的,这意味着它们在实际请求数据之前不会被执行,但是isEmpty()
是导致查询被执行的方法之一,它需要结果来判断是否有。
您的代码在之后设置查询缓存器配置,这将没有效果,因为查询对象的进一步评估/迭代将不会再次执行查询(这是通常会缓存其结果的时候),而是访问运行时缓冲的结果,因此没有数据被缓存。
如果你需要更多地控制缓存的处理方式,那么你可能想要避免内置的查询缓存,并完全手动完成,例如在必要时读取和写入缓存。
就您的用例而言,如果您有一个正在运行的删除和重新生成数据的脚本,您可能想要考虑使用它来清除缓存事后(bin/cake cache clear redis_cache
)。然后,如果你实现了">再试一次,直到有数据"前端的逻辑,你的后端代码可以简化为读取和缓存任何数据,如果还没有,你的前端会让用户知道数据还没有准备好,并再次轮询。虽然websockets或服务器发送的事件可能更好,但长轮询肯定比脚本连续运行几分钟更可取。