2015-06-17 18 views
9

W moim modelu PostSearch mam ten kod:Yii2: jak buforować aktywnego dostawcę danych?

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; 

moje spróbować, zamiast powyższej linii return $dataProvider, byłby to blok kodu:

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

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

return $result 

Chciałabym buforować wynik zwracany przez ADP, na podstawie pola updated_at. Chodzi mi o to, że chcę serwować dane z pamięci podręcznej, dopóki nie wprowadzi się jakiejś zmiany. Mój kod nie działa, mam na myśli buforowanie nie jest stosowane w ogóle. Co robię źle, i czy można to zrobić na ADP? Dzięki

Odpowiedz

13

Nie ma potrzeby używania buforowania dostawcy danych po utworzeniu, ponieważ w rzeczywistości nie robi żadnego wybierania w bazie danych, dopóki nie zostanie przygotowany. Tak więc faktycznie buforowałbyś pustą instancję obiektu taką, jaka jest teraz.

Jeśli masz bardzo duży zestaw rekordów, nazywamy DataProvider'ów prepare() z wyprzedzeniem w cache:

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

To rzeczywiście cache cokolwiek pyta się dataProvider działa, więc następnym razem będą pobierane z pamięci podręcznej zapytań. Powinno to doprowadzić do tego, czego szukasz.

Jeśli masz ograniczoną ilość zapisów buforowanie je wszystkie na raz może również pracować:

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

Oczywiście jest to mniej niż idealne dla dużych zbiorów danych, ale to zależy od tego, czego szukasz.

+0

Dziękuję, rozwiązanie z funkcją prepare() działa, ale nie rozumiem twojego drugiego kodu bardzo dobrze. Co to jest -> allModels i $ postActiveQuery? Dzięki jeszcze raz. – offline

+0

Właściwie wystarczyło '$ query'. Jest to ta sama zasada co pierwsza, ale zamiast tego pobieramy wszystkie rekordy i przechowujemy je w 'ArrayDataProvider'. Różnica polega na tym, że rzeczywiste modele/atrybuty są buforowane w pamięci podręcznej aplikacji, a nie w wynikach zapytania. Ale jeśli działa pierwszy, to trzymałbym się tego :) – Blizz

+0

@Blizz Przetestowałem twoje pierwsze rozwiązanie, które buforuje zapytanie 'select', ale nie buforuje zapytania' count' w dataProvider. Jak mogę to naprawić, aby buforować selekcje zarówno wybrane, jak i zliczone? Używam 'SqlDataProvider'. – hamed