it-swarm.com.de

Wie würden Sie zwischengespeicherte Eloquent-Modelle in Laravel vergessen?

Theoretische Frage zu Laravel hier.

Ein Beispiel für das Caching wäre:

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

Im Idealfall hätte ich gerne ein Ereignis für Artikelaktualisierungen. Wenn die ID einer Instanz dieses Modells (die bereits zwischengespeichert ist) aktualisiert wird, möchte ich diesen Schlüssel vergessen (auch wenn das gesamte Ergebnis der Abfrage vergessen wurde und nicht nur ist es möglich, dies zu tun?

Wenn nicht, gibt es eine Möglichkeit, dies einigermaßen sauber umzusetzen?

28
Peter Fox

Also suchte ich nach einer Antwort auf die gleiche Frage wie OP, war aber mit den Lösungen nicht wirklich zufrieden. Also habe ich vor kurzem angefangen, damit herumzuspielen und den Quellcode des Frameworks durchzugehen. Ich habe herausgefunden, dass die Methode remember() den zweiten Parameter key akzeptiert und aus irgendeinem Grund nicht in ihrem site (Oder habe ich das verpasst?).

Das Gute daran ist, dass der Database Builder denselben Cache-Treiber verwendet, der unter app/config/cache.php konfiguriert ist. Oder sollte ich dasselbe Cache-System angeben, das hier dokumentiert wurde - Cache . Wenn Sie also min und key an remember() übergeben, können Sie denselben Schlüssel zum Löschen des Caches mit der Methode Cache::forget() verwenden, und tatsächlich können Sie so ziemlich alle Cache -Methoden verwenden, die in aufgeführt sind. offizielle Seite , wie Cache::get(), Cache::add(), Cache::put() usw. Aber ich empfehle Ihnen nicht, diese anderen Methoden anzuwenden, es sei denn, Sie wissen, was Sie tun.

Hier ist ein Beispiel, damit Sie und andere verstehen, was ich meine.

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

Jetzt wird das obige Abfrageergebnis zwischengespeichert und dem Schlüssel article_comments zugeordnet, mit dem es jederzeit gelöscht werden kann (in meinem Fall mache ich es, wenn ich aktualisiere).

Also jetzt, wenn ich diesen Cache löschen möchte, unabhängig davon, wie viel Zeit es erinnert. Ich kann es einfach tun, indem ich Cache::forget('article_comments'); aufrufe und es sollte wie erwartet funktionieren.

Hoffe das hilft allen :)

59
Syed I.R

Ich denke, ein guter Weg ist wie this :

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

und dann verwenden Sie Model Observers , um das Ereignis der Aktualisierung des Modells zu erkennen

class UserObserver {

    public function saving($model)
    {
        //
    }

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

}

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

Ich habe den Debug-Modus getestet. Ich habe also festgestellt, dass Sie, wenn Sie einen Test für app.debug in einen Konstruktor einfügen, den mit einem Schlüssel verknüpften Cache leeren können. Sie sparen den Code für jede Funktion.

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

Derzeit gibt es keinen einfachen Weg. Ich habe jedoch diesen Workaround gefunden, der bisher für mich funktioniert hat.

Zuerst müssen Sie Illuminate\Database\Query\Builder erweitern.

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

Dann müssen Sie eine neue Klasse erstellen, die Eloquent Model erweitert.

<?php

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

        $grammar = $conn->getQueryGrammar();

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

Wenn Sie jetzt eloquente Modelle erstellen, erweitern Sie stattdessen Eloquent neu erstellte BaseModel.

Nun können Sie wie gewohnt remember das Ergebnis abfragen.

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

Wenn Sie das zwischengespeicherte Ergebnis löschen möchten, müssen Sie nur noch das tun

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

Wenn Sie sich bereits an das Ergebnis erinnern, speichert das Modell nach dem Löschen des zwischengespeicherten Ergebnisses das Ergebnis für diese Zeitspanne.

Hoffe das hilft.

0
tharumax