我正在尝试缓存查询,条件是在第一个请求之后,如果查询对象不为空,我希望缓存它我已经尝试了如下操作
public function getCategories()
{
$categoriesTable = TableRegistry::getTableLocator()->get( 'Categories' );
if(\Cake\Cache\Cache::read('categories', 'redis_cache') == null)
{
$categories = $categoriesTable->find();
if(!$categories->isEmpty())
{
print("hello");
$categories->cache('categories','redis_cache');
debug(\Cake\Cache\Cache::read('categories', 'redis_cache'));
}
$this->set('categories',$categories);
}else{
$this->set('categories',\Cake\Cache\Cache::read('categories', 'redis_cache'));
}
$this->viewBuilder()->setOption('serialize', ['categories']);
}
我从 Postman 那里得到的输出
第一次命中
hello
null
第2次命中
hello
null
但在注解if(!$categories->isEmpty())
条件后
第一次命中
{
"categories": [
{
"id": 2,
...
}
另外,如果我写的条件像下面一样,它也工作得很好。
if(!$categoriesTable->find('all')->isEmpty()). // it's working
我在这里做错了什么?
1条答案
按热度按时间ffscu2ro1#
查询是延迟求值的,这意味着在实际请求数据之前不会执行它们,但是
isEmpty()
是将导致执行查询的方法之一,它需要结果来告诉是否存在查询。您的代码设置了查询缓存器配置 * afterhater ,这将不会产生任何影响,因为查询对象的进一步求值/迭代将不会再次执行查询(这是它通常缓存其结果的时候),而是访问运行时缓冲的结果,因此不会缓存任何数据。
如果您需要对如何处理缓存进行更多的控制,那么您可能希望避免使用内置的查询缓存,而完全手动完成,例如根据需要读取和 * 写入该高速缓存。
就您的用例而言,如果您运行了一个删除和重新生成数据的脚本,那么您可能需要考虑使用它来执行clear the cache操作(
bin/cake cache clear redis_cache
)。然后,如果您在前端实现“ 重试,直到有数据 *”逻辑,您的后端代码可以简化为只读取和缓存有数据的任何数据,如果还没有,你的前端会让用户知道数据还没有准备好,然后再次轮询。虽然websockets或服务器发送的事件可能更好,但长时间的轮询肯定比让脚本连续运行几分钟更好。