Eloquent::remember
// 从数据库中取出前5个用户,并缓存结果。
User::remember(10)->take(5)->get();
// 下面这句会缓存posts么?
User::with(array('posts'))->remember(10)->take(5)->get();
先找一下remember
在哪定义的!
remember 方法的定义
# grep -nC1 "Eloquent" app/config/app.php
150- 'DB' => 'Illuminate\Support\Facades\DB',
151: 'Eloquent' => 'Illuminate\Database\Eloquent\Model',
152- 'Event' => 'Illuminate\Support\Facades\Event',
# grep -nC3 "function remember(" vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php
1086- * @param string $key
1087- * @return \Illuminate\Database\Query\Builder|static
1088- */
1089: public function remember($minutes, $key = null)
1090- {
1091- list($this->cacheMinutes, $this->cacheKey) = array($minutes, $key);
1092-
这里Eloquent
是Model
的一个别名,而Model
中并没有定义remember
方法,而是用了装饰者设计模式
通过__call
魔术方法调用了Builder
的方法。其实他是在内部实例化Builder
的,有点“反向代理”的意思。
Builder
在调用remember
的时候做了个标记,在get
的时候对这个标记作了判断,对查询结果做了缓存的写入和读取。这就不难理解remember
方法只会对单个query查询结果进行缓存。
回头看
User::with(array('posts'))->remember(10)->take(5)->get();
使用with
只是将1 + 5 * 1
次query,优化成了1 + 1
次;而不是想象中的一次缓存该条语句产生的所有query的结果。
缓存关联Model
User::with(array('posts' => function ($query)
{
return $query->remember(10);
}))->remember(10)->take(5)->get();
当然,在定义model relation的时候也可以将 remember() 跟在后面,但我不认为这是一个好的方法。
function posts()
{
return $this->hasMany('Post')->remember(10);
}