Подтвердить что ты не робот

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

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

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

Article::with('comments')->remember(5)->get();

В идеале я хотел бы иметь событие для обновлений статьи, когда при обновлении идентификатора экземпляра этой модели (который уже кэширован) я хочу забыть этот ключ (даже если это весь результат запроса, который был забыт а не только один экземпляр модели), это можно сделать?

Если нет способа реализовать это достаточно чисто?

4b9b3361

Ответ 1

Итак, я искал ответ на тот же вопрос, что и 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');, и он должен работать так, как ожидалось.

Надеюсь, это поможет всем:)

Ответ 2

Я думаю, что хороший способ - это this:

$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);

Ответ 3

В настоящее время нет простого способа. Однако я нашел это решение, которое до сих пор работало для меня.

Сначала вы должны расширить 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 Модели расширяют только созданный BaseModel.

Теперь вы можете выполнить результат запроса remember как обычно.

YourModel::remember(10)->get();

Если вы хотите отказаться от кэшированного результата, все, что вам нужно сделать, это

YourModel::forget()->get();

Если вы запомнили результат ранее, после очистки кэшированного результата, модель продолжит запоминать результат за этот промежуток времени.

Надеюсь, что это поможет.

Ответ 4

Я тестировал режим отладки. Поэтому я обнаружил, что если вы поместите тест для 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;
    }
}