Как вы могли бы забыть кешированные модели Eloquent в Laravel?

Здесь теоретический вопрос о Ларавеле.

Итак, пример кэширования, который я бы сделал, это:

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; } }