CakePHP 3.x ORM 如何在不显式定义的情况下知道要读取哪个缓存文件?
How does CakePHP 3.x ORM know which cache file to read from without explicitly defining it?
CakePHP 3.5.13
在控制器方法中,我按如下方式缓存数据库查询:
$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 对此进行解释。它说:
The cache method makes it simple to add cached results to your custom finders or through event listeners.
When the results for a cached query are fetched...
它告诉您如何写入(添加)缓存,而不是从缓存中读取(获取)关于 ORM。
我已经阅读了文档的某些部分,这些部分告诉您如何以一般的、非 ORM 特定的方式(使用 Cache::read($key)
)从缓存中读取数据,但这与让 ORM 执行它完全不同自动地。在 Cache::read($key)
的情况下,您必须提供一个密钥 ($key
) 来告诉它从哪个缓存文件读取数据 - 我可以理解这一点,因为您明确告诉它要读取哪个密钥读。但 ORM 和查询对象并非如此。
有人可以澄清一下吗?
CookBook 很可能没有提到额外的要求,因为没有。
写的缓存key当然要和读的缓存key一样,其他都不行从某种意义上说,即查询将使用您传递给 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.
*
* [...]
*/
每次执行查询时,它都会检查您是否传递了缓存键,并评估并使用它来相应地读取和写入缓存结果。因此,您必须确保缓存键是 "static" 才能使整个查询缓存有用。
您可以使用闭包来动态构建密钥,但结果必须是静态的,即对于相同的查询,它必须在每次被调用时生成相同的密钥。 QueryTrait::cache()
方法不仅接受闭包,而且接受字符串,这是有原因的!
我之前提到过,这发生在 \Cake\Datasource\QueryTrait::all()
and \Cake\Datasource\QueryCacher::fetch()
,请查看源代码以更好地了解它的工作原理。
CakePHP 3.5.13
在控制器方法中,我按如下方式缓存数据库查询:
$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 对此进行解释。它说:
The cache method makes it simple to add cached results to your custom finders or through event listeners.
When the results for a cached query are fetched...
它告诉您如何写入(添加)缓存,而不是从缓存中读取(获取)关于 ORM。
我已经阅读了文档的某些部分,这些部分告诉您如何以一般的、非 ORM 特定的方式(使用 Cache::read($key)
)从缓存中读取数据,但这与让 ORM 执行它完全不同自动地。在 Cache::read($key)
的情况下,您必须提供一个密钥 ($key
) 来告诉它从哪个缓存文件读取数据 - 我可以理解这一点,因为您明确告诉它要读取哪个密钥读。但 ORM 和查询对象并非如此。
有人可以澄清一下吗?
CookBook 很可能没有提到额外的要求,因为没有。
写的缓存key当然要和读的缓存key一样,其他都不行从某种意义上说,即查询将使用您传递给 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.
*
* [...]
*/
每次执行查询时,它都会检查您是否传递了缓存键,并评估并使用它来相应地读取和写入缓存结果。因此,您必须确保缓存键是 "static" 才能使整个查询缓存有用。
您可以使用闭包来动态构建密钥,但结果必须是静态的,即对于相同的查询,它必须在每次被调用时生成相同的密钥。 QueryTrait::cache()
方法不仅接受闭包,而且接受字符串,这是有原因的!
我之前提到过,这发生在 \Cake\Datasource\QueryTrait::all()
and \Cake\Datasource\QueryCacher::fetch()
,请查看源代码以更好地了解它的工作原理。