2015-06-17 16 views
9

Nel mio modello PostSearch ho questo codice:Yii2: come memorizzare nella cache il fornitore di dati attivo?

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; 

il mio tentativo, invece di sopra della linea return $dataProvider, sarebbe questo blocco di codice:

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

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

return $result 

Vorrei mettere in cache il risultato restituito da ADP, basato sul campo updated_at. Voglio dire, voglio servire i dati dalla cache fino a quando non vengono apportate alcune modifiche. Il mio codice non funziona, voglio dire che il caching non viene applicato affatto. Cosa sto facendo male, ed è possibile farlo su ADP? Grazie

risposta

13

Ha poca utilità di memorizzare nella cache il fornitore di dati dopo l'istanziazione, dal momento che non sta effettuando alcuna selezione sul database finché non è stato preparato. Quindi in effetti si memorizzerebbe nella cache un'istanza di oggetto vuoto come ora.

Se si dispone di un grande insieme di record, chiamare i dataProviders' prepare() in anticipo nella cache:

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

Questo effettivamente cache di qualsiasi interroga i dataProvider piste, così la prossima volta che saranno recuperati dalla cache della query. Questo dovrebbe risultare in ciò che stai cercando.

Se si dispone di una quantità limitata di record, tutti in una volta caching potrebbe anche funzionare:

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

Ovviamente questo è proprio l'ideale per i set di dati più grandi, ma dipende da quello che stai cercando.

+0

Grazie, la soluzione con prepare() funziona, ma non capisco molto bene il tuo secondo codice. Cosa sono -> allModels e $ postActiveQuery? Grazie ancora. – offline

+0

In realtà era sufficiente '$ query'. È lo stesso principio del primo pezzo, ma recuperiamo tutti i record e li memorizziamo in un 'ArrayDataProvider'. La differenza è che ora i modelli/gli attributi effettivi vengono memorizzati nella cache dell'applicazione invece dei risultati della query. Ma se il primo funziona, vorrei attenermi a quello :) – Blizz

+0

@Blizz Ho provato la tua prima soluzione, quella cache 'select' query, ma non memorizza nella cache la query' count' di dataProvider. Come posso risolvere questo problema per memorizzare nella cache sia le coppie di selezione che quelle di conteggio? Sto usando 'SqlDataProvider'. – hamed