web-dev-qa-db-fra.com

Comment oublierais-tu les modèles Eloquent en cache à Laravel?

Question théorique sur Laravel ici.

Ainsi, l'exemple de la mise en cache que je ferais est:

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

Idéalement, j'aimerais avoir un événement pour les mises à jour d'article lorsque, lors de la mise à jour de l'ID d'une instance de ce modèle (déjà mis en cache), je souhaite oublier cette clé cette instance de modèle), il est possible de le faire?

Sinon, y a-t-il un moyen d'appliquer cela raisonnablement proprement?

28
Peter Fox

Je pense qu'une bonne façon de faire est comme this :

$value = Cache::remember('users', $minutes, function()
{
    return DB::table('users')->get();
});

puis utilisez Model Observers pour détecter l'événement de mise à jour du modèle.

class UserObserver {

    public function saving($model)
    {
        //
    }

    public function saved($model)
    {
        // forget from cache
        Cache::forget('users');
    }

}

User::observe(new UserObserver);
13
Glad To Help

Je testais pour le mode débogage. J'ai donc constaté que si vous mettez un test pour app.debug dans un constructeur, vous pouvez vider le cache associé à une clé. Vous évite de dupliquer le code pour chaque fonction.

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;
    }
}
0
Lionel Morrison

Actuellement, il n'y a pas de moyen facile. Cependant, j'ai trouvé cette solution de contournement, qui jusqu'à présent a fonctionné pour moi.

Vous devez d’abord étendre 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);
    }
}

Ensuite, vous devez créer une nouvelle classe qui étend Eloquent Model.

<?php

class BaseModel extends Eloquent {
    protected function newBaseQueryBuilder() {
        $conn = $this->getConnection();

        $grammar = $conn->getQueryGrammar();

        return new ModifiedBuilder($conn, $grammar, $conn->getPostProcessor());
    }
}

Maintenant, lors de la création de modèles Eloquent, au lieu d'étendre Eloquent, les modèles étendent la nouvelle BaseModel créée.

Vous pouvez maintenant utiliser le résultat de la requête remember comme d'habitude.

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

Lorsque vous souhaitez supprimer le résultat mis en cache, il vous suffit de

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

Si vous vous souvenez du résultat précédemment, après avoir effacé le résultat mis en cache, le modèle continuera à mémoriser le résultat pendant cette période.

J'espère que cela t'aides.

0
tharumax