CakePHP 3.5.13
在Controller方法中,我缓存数据库查询如下:
$substances = TableRegistry::get('Substances');
$query = $substances->find()->limit($limit)->offset($offset);
$query->cache(function ($query) {
return 'substance_results_' . md5(serialize($query->sql()));
});
$this->set('data', $query->all());这将生成一个缓存文件(我们在此应用程序中使用Redis缓存),其中包含查询的结果。例如,我可以在Redis中看到以下内容:
127.0.0.1:6379> keys *
3) "cake_redis_substance_results_cb799f6526c148d133ad9ce9245b23be"
4) "cake_redis_substance_results_dbc7b0b99dff3ab6a20cbdfbbd09be8c"如果再次执行相同的查询($query),Cake将读取适当缓存文件的内容。,既然我们没有告诉它要从哪个键读取缓存的数据,这怎么可能呢?,我们告诉它要写的键的名称,而不是读取的键的名称。
为了进一步说明这一点,假设我这样做了:
$query->cache(function ($query) {
return 'foo_' . md5(serialize(time()));
});在这里,我创建了一个完全不同的键,而不是基于正在执行的SQL。代码的任何部分都不会告诉它哪个键对应于哪个查询。
关于缓存加载结果的文档(https://book.cakephp.org/3.0/en/orm/query-builder.html#caching-loaded-results)没有解释这与ORM有关。上面写着:
cache方法使将缓存结果添加到自定义查找程序或通过事件侦听器变得简单。 当缓存查询的结果是获取的时.
它告诉您如何向缓存中写入(添加),而不是从缓存中读取(获取)与ORM有关的内容。
我已经阅读了一些文档,这些部分告诉您如何以一种通用的、非ORM特定的方式从缓存中读取(使用Cache::read($key)),但这与让ORM自动读取是完全不同的。在Cache::read($key)的情况下,您必须提供一个键($key),它告诉它要从哪个缓存文件读取数据--我可以理解这一点,因为您正在显式地告诉它要读取哪个键。但ORM和query对象的情况并非如此。
有人能澄清一下吗?
发布于 2018-09-28 14:15:56
CookBook最有可能没有提到额外的需求,因为没有任何需求。
当然,用于写入的缓存键必须与用于读取的缓存键相同,其他任何内容都没有任何意义(查询将使用传递给QueryTrait::cache()方法的任何内容,即读取和写入,这意味着要在传递的闭包中显式定义读取键。
看看the method description,它说的差不多是一样的:
/**
* Enable result caching for this query.
*
* If a query has caching enabled, it will do the following when executed:
*
* - Check the cache for $key. If there are results no SQL will be executed.
* Instead the cached results will be returned.
* - When the cached data is stale/missing the result set will be cached as the query
* is executed.
*
* ### Usage
*
* ```
* // Simple string key + config
* $query->cache('my_key', 'db_results');
*
* // Function to generate key.
* $query->cache(function ($q) {
* $key = serialize($q->clause('select'));
* $key .= serialize($q->clause('where'));
* return md5($key);
* });
*
* [...]
*
* @param false|string|\Closure $key Either the cache key or a function to generate the
* cache key. When using a function, this query instance will be supplied as an argument.
*
* [...]
*/每次执行查询时,它都会检查您是否传递了缓存键,并相应地评估和使用它来读取和写入缓存的结果。因此,您必须确保缓存键是“静态的”,以便使整个查询缓存功能发挥任何作用。
您可以使用闭包动态构建密钥,但是结果必须是静态的,即对于同一个查询,每次调用时都必须生成相同的键。QueryTrait::cache()方法不仅接受闭包,而且接受字符串,这是有原因的!
我之前已经提到过,这发生在\Cake\Datasource\QueryTrait::all()和\Cake\Datasource\QueryCacher::fetch()中,请查看源代码,以更好地理解它的工作原理。
https://stackoverflow.com/questions/52556533
复制相似问题