Как CakePHP 3.x ORM узнает, из какого файла кэша нужно прочитать, не определяя его явно? - PullRequest
0 голосов
/ 28 сентября 2018

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. Она говорит:

Метод кэширования упрощает добавление кэшированных результатов в пользовательские искатели или через прослушиватели событий.

Когда результаты для кэшированного запроса fetched ...

Он говорит вам, как записать (добавить) в кеш, но не прочитать (извлечь) из него относительно ORM.

Я прочиталразделы документации, в которых рассказывается о том, как читать из кэша обычным, не зависящим от ORM способом (используя Cache::read($key)), но это совершенно отдельно от того, чтобы ORM делал это автоматически. В случае Cache::read($key) you 'мне нужно предоставить ключ ($key), который сообщает ему, из какого файла кэша нужно прочитать данные - я могу понять это, поскольку вы явно указываете, какой ключ читать. Но это не относится к ORM и объектам запросов..

Пожалуйста, кто-нибудь может уточнить это?

1 Ответ

0 голосов
/ 28 сентября 2018

В CookBook, скорее всего, не упоминаются дополнительные требования, потому что их нет.

Ключ кэша для записи , конечно, должен совпадать с ключом кэша для чтение , все остальное не имеет никакого смысла, т. Е. Запрос будет использовать все, что вы передадите методу QueryTrait::cache() как для чтения, так и для записи, что означает, что вы явно определяете ключ для чтения, прямо в закрытии, которое вы передаете.

Проверьте описание метода , оно в значительной степени говорит то же самое:

/**
 * 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(), взгляните на источник, чтобы лучше понять, как он работает.

...