Здесь теоретический вопрос о Ларавеле.
Итак, пример кэширования, который я бы сделал, это:
Article::with('comments')->remember(5)->get();
В идеале я хотел бы иметь событие для обновлений статьи, когда обновляется идентификатор экземпляра этой модели (который уже кэширован). Я хочу забыть этот ключ (даже если это весь результат запроса, который был забыт, а не просто что один экземпляр модели), это можно сделать?
Если нет, то какой-то способ реализовать это достаточно чисто?
Поэтому я искал ответ на тот же вопрос, что и OP, но на самом деле не был удовлетворен решениями. Поэтому я начал играть с этим недавно и просматривал исходный код фреймворка, я узнал, что метод remember()
принимает второй параметр, называемый key
и по какой-то причине он не был зарегистрирован на их сайте (или я пропустил это ?).
Теперь хорошая вещь в том, что в построителе базы данных используется один и тот же драйвер кэша, который настроен в app/config/cache.php
Или я должен сказать, что такая же система кэширования была зарегистрирована здесь – Cache . Поэтому, если вы передаете min и key для remember()
, вы можете использовать один и тот же ключ для очистки кеша с помощью метода Cache::forget()
и на самом деле вы можете использовать все методы Cache
перечисленные на официальном сайте , например Cache::get()
, Cache::add()
, Cache::put()
и т. Д. Но я не рекомендую вам использовать эти другие методы, если вы не знаете, что делаете.
Вот пример для вас и других, чтобы понять, что я имею в виду.
Article::with('comments')->remember(5, 'article_comments')->get();
Теперь приведенный выше результат запроса будет кэшироваться и будет связан с ключом article_comments
который затем может быть использован для его очистки в любое время (в моем случае я делаю это при обновлении).
Итак, теперь, если я хочу очистить этот кеш, независимо от того, сколько времени он запоминает. Я могу просто сделать это, вызвав Cache::forget('article_comments');
и он должен работать так, как ожидалось.
Надеюсь, это поможет всем 🙂
Я думаю, что хороший способ сделать это так:
$value = Cache::remember('users', $minutes, function() { return DB::table('users')->get(); });
а затем используйте Model Observers для обнаружения события обновления модели
class UserObserver { public function saving($model) { // } public function saved($model) { // forget from cache Cache::forget('users'); } } User::observe(new UserObserver);
В настоящее время нет простого способа. Однако я нашел это обходное решение, которое до сих пор работало для меня.
Сначала вам нужно расширить Illuminate\Database\Query\Builder
.
<?php class ModifiedBuilder extends Illuminate\Database\Query\Builder { protected $forgetRequested = false; public function forget() { $this->forgetRequested = true; } public function getCached($columns = array('*')) { if (is_null($this->columns)) $this->columns = $columns; list($key, $minutes) = $this->getCacheInfo(); // If the query is requested ot be cached, we will cache it using a unique key // for this database connection and query statement, including the bindings // that are used on this query, providing great convenience when caching. $cache = $this->connection->getCacheManager(); $callback = $this->getCacheCallback($columns); if($this->forgetRequested) { $cache->forget($key); $this->forgetRequested = false; } return $cache->remember($key, $minutes, $callback); } }
Затем вам нужно создать новый класс, который расширяет Eloquent Model.
<?php class BaseModel extends Eloquent { protected function newBaseQueryBuilder() { $conn = $this->getConnection(); $grammar = $conn->getQueryGrammar(); return new ModifiedBuilder($conn, $grammar, $conn->getPostProcessor()); } }
Теперь, создавая Eloquent Models, вместо расширения Eloquent
Models расширяется только что созданный BaseModel
.
Теперь вы можете remember
результат запроса, как обычно.
YourModel::remember(10)->get();
Если вы хотите отказаться от кэшированного результата, все, что вам нужно сделать, это
YourModel::forget()->get();
Если вы запомнили результат ранее, после очистки кэшированного результата, модель продолжит запоминать результат за этот промежуток времени.
Надеюсь это поможет.
Я тестировал режим отладки. Поэтому я обнаружил, что если вы поместите тест для app.debug в конструктор, вы сможете очистить кеш, связанный с ключом. Сохраняет дублирование кода для каждой функции.
class Events { public function __construct() { if (\Config::get('app.debug')) { Cache::forget('events'); } } public static function all() { $events = \DB::table('events as e') ->select('e.*') ->where('enabled', 1) ->remember(30, 'events') ->get(); return $events; } }