2013-10-23 8 views
28

Theoretische Frage zu Laravel hier.Wie würden Sie im Galaktischen Erequenz Modelle in Laravel vergessen?

So Beispiel des Caching ich tun würde:

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

Idealerweise möchte ich ein Ereignis haben, für Artikel aktualisiert, dass, wenn die ID einer Instanz dieses Modells (das ist bereits im Cache) ist aktualisiert Ich möchte diesen Schlüssel vergessen (auch wenn das gesamte Ergebnis der Abfrage vergessen wurde und nicht nur diese eine Modellinstanz), ist es möglich, dies zu tun?

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

+0

nicht so theoretisch, btw. –

+0

Nicht jetzt ist es beantwortet, aber zu der Zeit war es, weil es keine Dokumentation zur Verwendung von Cache-Schlüssel mit beredten –

Antwort

59

Also ich war auf der Suche nach einer Antwort auf die gleiche Frage wie OP, war aber nicht wirklich zufrieden mit den Lösungen. Also habe ich vor kurzem damit angefangen, mit dem Quellcode des Frameworks zu experimentieren. Ich habe herausgefunden, dass die remember() Methode den zweiten Param namens key akzeptiert und aus irgendeinem Grund nicht auf ihrer site dokumentiert wurde (Oder habe ich das vermisst?) .

Nun, das ist gut, dass der Datenbank-Builder den gleichen Cache-Treiber verwendet, der unter app/config/cache.php konfiguriert ist. Oder sollte ich das gleiche Cache-System sagen, das hier dokumentiert wurde - Cache. Also, wenn Sie min und Schlüssel zum remember() geben, können Sie den gleichen Schlüssel verwenden, um den Cache mit Cache::forget() Methode zu löschen und in der Tat kann man ziemlich viel verwenden, um all Cache aufgeführten Methoden auf den official site, wie Cache::get(), Cache::add(), Cache::put() usw. Aber ich empfehle Ihnen nicht, diese anderen Methoden zu verwenden, wenn Sie nicht wissen, was Sie tun.

Hier ist ein Beispiel für Sie und andere zu verstehen, was ich meine.

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

Nun ist die obige Abfrage-Ergebnis wird im Cache gespeichert werden und wird mit dem article_comments Schlüssel, dann ist es jederzeit löschen verwendet werden können, in Verbindung gebracht werden (In meinem Fall habe ich es tun, wenn ich aktualisieren).

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

hoffe, das hilft jeder :)

+3

Gute Antwort, danke. Für diejenigen, die unklar sind, das erste Argument zu erinnern ist die Anzahl der Minuten zu cache. Http: // Laravel .com/api/source-class-Illuminate.Database.Query.Builder.html # 881-893 – Makita

+1

Kein Problem und danke für den Link –

+0

diese gute Frage und nützliche Antwort sollte upvote :) – antoniputra

12

Ich denke, ein guter Weg ist, wie this zu tun:

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

und dann Model Observers verwenden, um die Veranstaltung der Aktualisierung des Modells

class UserObserver { 

    public function saving($model) 
    { 
     // 
    } 

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

} 

User::observe(new UserObserver); 
+0

gab Wenn ich DB :: table ('Benutzer') -> get(); Dies wird nicht Instanzen eines Eloquent-Modells erhalten, wird es nur die Ergebnisse der Abfrage als ein Array von generischen Objekten erhalten? Dachte ich nehme an, ich kann das Ergebnis der Eloquent-Modell-Abfrage anstelle einer direkten DB-Abfrage zurückgeben? –

+0

Ich glaube, du solltest 'User :: whereSomething ('something') -> get()' verwenden, wenn du die Eloquent-Sammlung von Objekten zwischenspeichern möchtest und die Eigenschaften einfach in ein Array wie: 'speichern willst Benutzer :: whereSomething ('etwas') -> get() -> toArray() '. –

0

Momentan gibt es keine einfache Möglichkeit, zu erkennen. Allerdings habe ich diese Problemumgehung gefunden, die 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 neue Klasse erstellen, die Eloquent-Modell erweitert. Jetzt

<?php 

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

     $grammar = $conn->getQueryGrammar(); 

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

beim Erstellen Eloquent Models statt erstreckenden Eloquent Models erstrecken neu BaseModel erstellt.

Jetzt können Sie remember Abfrage Ergebnis wie üblich.

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

Wenn Sie das zwischengespeicherte Ergebnis verwerfen alles, was Sie tun müssen, ist

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

Wenn Sie das Ergebnis vorher erinnern, nachdem die zwischengespeicherte Ergebnis löschen, wird Modell weiterhin das Ergebnis für das erinnern, Zeitraum.

Hoffe, das hilft.

+0

In der getCached-Methode, wo wird die Schlüsselvariable $ initiiert? –

+0

Es wird in 'getCacheInfo()' Funktion abgerufen und der Schlüssel wird generiert in 'generateCacheKey()' Funktion in ['Illuminate/Datenbank/Query/Builder.php'] (https://github.com/laravel/framework/ Blob/Master/src/Illuminate/Datenbank/Abfrage/Builder.php). Anscheinend können Sie Ihren eigenen Schlüssel mit der Methode 'remember()' gemäß der API festlegen. Es scheint jedoch in der 'getCacheKey()' -Funktion vernachlässigt zu werden. – tharumax

+0

Die Methode, die ich oben erwähnte, funktioniert ziemlich gut für die einfachen Abfragen und die meisten Beziehungen. Allerdings, wenn Pivot-Tabelle vorhanden ist (in vielen zu viele Beziehungen funktioniert es nicht wie erwartet. – tharumax

0

ich für Debug-Modus zu testen wurde. Also habe ich festgestellt, dass Sie, wenn Sie einen Test für app.debug in einen Konstruktor einfügen, den Cache löschen können, der mit einem Schlüssel verknüpft ist. Spart es, dass Sie den Code für jede Funktion duplizieren müssen.

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