Perl の DBIC みたいに cache_for とかで データをキャッシュしたいな~と思ったので Eloquentを拡張してみました。
つまりこんな感じでキャッシュできるといいなー
$books = Books::with('Authors')
->where('is_enabled','=',1)
->cache_for(100)
->get();
class EloquentPluginQuery extends Laravel\Database\Eloquent\Query {
protected function query()
{
return new EloquentPluginQuery($this);
}
}
class EloquentPluginQuery extends Laravel\Database\Eloquent\Query {
private $cache_time = 30;
private $is_cached = 0;
public function get($columns = array('*'))
{
if (is_null($columns)) $columns = array('*');
$cached_key = $this->generate_cached_key(__FUNCTION__,$columns);
if ( $this->is_cached and Cache::has( $cached_key ) )
return unserialize( Cache::get( $cached_key ) );
$value = parent::get($columns);
Cache::put( $cached_key ,serialize($value) ,$this->cache_time ) ;
return $value;
}
public function paginate($per_page = null, $columns = array('*'))
{
if (is_null($columns)) $columns = array('*');
$cached_key = $this->generate_cached_key(__FUNCTION__,$columns,$per_page);
if ( $this->is_cached and Cache::has( $cached_key ) )
return unserialize( Cache::get( $cached_key ) );
$value = parent::paginate($per_page,$columns);
Cache::put( $cached_key ,serialize($value) ,$this->cache_time ) ;
return $value;
}
public function first($columns = array('*'))
{
if (is_null($columns)) $columns = array('*');
$cached_key = $this->generate_cached_key(__FUNCTION__,$columns);
if ( $this->is_cached and Cache::has( $cached_key ) )
return unserialize( Cache::get( $cached_key ) );
$value = parent::first($columns);
Cache::put( $cached_key ,serialize($value) ,$this->cache_time ) ;
return $value;
}
private function generate_cached_key( $method , $columns,$per_page=0 )
{
$t = $this->table;
$t->select($columns);
$sql = $t->grammar->select($t);
$bindings = serialize($t->bindings);
$page = Input::get('page', 1);
$cached_key = "$method|$sql|$bindings|$page|$per_page";
return md5($cached_key);
}
public function cache_for($time=null)
{
if ($time) $this->cache_time = $time;
$this->is_cached = 1;
return $this;
}
}
モデルを以下に変更
class Books extends Eloquent {....}
↓
class Books extends EloquentPluginModel {....}
これで cache_for()を使えるようになるので キャッシュがあれば そちからか なければ SQLを発行するようになります。
ただ、withでrelationテーブルを指定するとデータ自体はリレーション先までキャッシュされてるけど、実際 テンプレート上で $book->author->first()->author_name とかするとSQL発行されちゃうので キャッシュされたデータは $books['relationships']を参照する必要がでてきちゃう。
$book->author->first()->author_name できるように relation関連のソースも拡張すれば可能かもしれないけど 今回は面倒なのでやめちゃいました。
どなたかもっとよい方法あれば教えてください<(_ _)>