理解Laravel Eloquent的cache

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-

这里EloquentModel的一个别名,而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);
}

标签: none

添加新评论