2015-06-17 10 views
9

In meinem PostSearch Modell habe ich diesen Code:Yii2: Wie aktiver Datenanbieter im Cache?

public function search($params) 
{ 
    $query = Post::find()->where(['status' => 1]); 

    $dataProvider = new ActiveDataProvider([ 
     'query' => $query, 
     'sort'=> ['defaultOrder' => ['id' => SORT_DESC]], 
     'pagination' => [ 
      'pageSize' => 10, 
     ] 
    ]); 

    if (!($this->load($params) && $this->validate())) { 
     return $dataProvider; 
    } 

    $query->andFilterWhere([ 
     'id' => $this->id, 
     'status' => $this->status, 
    ]); 

    $query->andFilterWhere(['like', 'title', $this->title]) 
     ->andFilterWhere(['like', 'text', $this->text]); 

    return $dataProvider; 

meinen Versuch, statt über die Linie return $dataProvider, dieser Block von Code wäre:

$dependency = [ 
    'class' => 'yii\caching\DbDependency', 
    'sql' => 'SELECT MAX(updated_at) FROM post', 
]; 

$result = self::getDb()->cache(function ($db) { 
    return $dataProvider; 
}, 3600, $dependency); 

return $result 

Ich kehrt um das Ergebnis cachen möchte ADP, basierend auf dem Feld updated_at. Ich meine, ich möchte Daten aus dem Cache liefern, bis etwas geändert wird. Mein Code funktioniert nicht, ich meine, Caching wird überhaupt nicht angewendet. Was mache ich falsch, und ist es möglich, dies auf ADP zu tun? Danke

Antwort

13

Es hat wenig Nutzen, den Datenprovider nach dem Instanziieren zwischenzuspeichern, da es tatsächlich keine Auswahl in der Datenbank vornimmt, bis es vorbereitet wurde. Sie würden also eine leere Objektinstanz im Cache speichern, so wie es jetzt ist.

Wenn Sie eine sehr große Menge von Datensätzen haben, rufen Sie die Dataprovider prepare() vorab im Cache:

self::getDb()->cache(function ($db) use ($dataProvider) { 
    $dataProvider->prepare(); 
}, 3600, $dependency); 
return $dataProvider; 

Dies wird, was tatsächlich Cache die dataProvider läuft abfragt, also das nächste Mal werden sie abgeholt werden aus dem Abfrage-Cache. Dies sollte dazu führen, was Sie suchen.

Wenn Sie eine endliche Menge von Datensätzen haben, das Caching sie alle auf einmal könnte auch arbeiten:

$key = 'MyCachedData'; // + Data uniquely referring to your search parameters 
$cache = \Yii::$app->cache; 
$dataProvider = $cache->get($key); 
if (!$dataProvider) { 
    $dependency = \Yii::createObject([ 
     'class' => 'yii\caching\DbDependency', 
     'sql' => 'SELECT MAX(updated_at) FROM post', 
    ]); 

    $dataProvider = new \yii\data\ArrayDataProvider; 
    $dataProvider->allModels = $query->all(); 
    $cache->set($key, $dataProvider, 3600, $dependency) 
} 
return $dataProvider; 

Offensichtlich ist dies weniger als ideal für größere Datensätze, aber es hängt davon ab, was Sie suchen.

+0

Danke, Lösung mit Prepare() funktioniert, aber ich verstehe Ihren zweiten Code nicht sehr gut. Was ist -> allModels und $ postActiveQuery? Danke noch einmal. – offline

+0

Eigentlich war nur '$ query' genug. Es ist das gleiche Prinzip wie das erste Stück, aber stattdessen holen wir alle Datensätze und speichern sie in einem 'ArrayDataProvider'. Der Unterschied besteht darin, dass die tatsächlichen Modelle/Attribute jetzt im Anwendungscache zwischengespeichert werden und nicht mehr die Ergebnisse der Abfrage. Aber wenn der erste funktioniert, würde ich bei diesem bleiben :) – Blizz

+0

@Blizz Ich testete Ihre erste Lösung, die '' '' 'Abfrage 'zwischenspeichert, aber nicht' count' Abfrage von DataProvider. Wie kann ich dies beheben, um sowohl die Auswahl als auch die Anzahl der Warteschlangen zwischenzuspeichern? Ich benutze 'SqlDataProvider'. – hamed