【问题标题】:Laravel 4 eager loadingLaravel 4 急切加载
【发布时间】:2014-08-13 23:29:38
【问题描述】:

我有一个User 模型、一个Recipe 模型和一个Cookbook 模型。

用户可以“拥有”许多食谱。 (用户 -OneToMany- 配方)

一个用户“只有一个”食谱。 (用户 -OneToOne- Cookbook)

用户拥有的食谱属于他的食谱。 一份食谱可以属于多本食谱。 (食谱分享)(Cookbook -ManyToMany- Recipe)

许多用户可能喜欢许多食谱。 (用户 -ManyToMany- 配方)

许多用户可以关注许多食谱。 (用户 -ManyToMany- Cookbook)

一个用户可以有很多朋友是用户(User -OneToMany- User)


我要做的是为当前登录的用户加载食谱。

我想加载他朋友拥有的食谱以及登录用户正在关注的所有食谱的食谱


class User extends Eloquent {
    public function friends() {
        return $this->belongsToMany('User', 'user_friends', 'user_id', 'friend_id');
    }

    public function cookbook() {
        return $this->hasOne('Cookbook', 'owner_id', 'id');
    }

    public function recipes() {
        return $this->hasMany('Recipe', 'owner_id', 'id');
    }

    public function followedCookbooks() {
        return $this->belongsToMany('Cookbook','cb_followers', 'follower_id', 'cb_id');
    }
}

class Recipe extends Eloquent() {
    public function owner() {
        return $this->belongsTo('User', 'owner_id', 'id');
    }

    public function cookbooks() {
        return $this->belongsToMany('Cookbook', 'cb_recipes', 'recipe_id', 'cb_id');
    }
}

class Cookbook extends Eloquent() {
    public function owner() {
        return $this->belongsTo('User', 'owner_id', 'id');
    }

    public function recipes() {
        return $this->belongsToMany('Recipe', 'cookbooks_recipes', 'cookbook_id', 'recipe_id');
    }

    public function followers() {
        return $this->belongsToMany('User', 'cb_followers', 'cb_id', 'follower_id');
    }
}

我做的是这样的:

$user = Auth::user();

$friends = $user->friends();
$cookbooks = $user->followedCookbooks();

$recipes = array();

foreach($friends as $friend) {
    $recipe = $friend->recipes();
    array_push($recipes, $recipe);
}

foreach($cookbooks as $cookbook) {
    $cbRecipes = $cookbook->recipes()
    foreach($cbRecipes as $cbRecipe) {
        array_push($recipes, $cbRecipe);
    }
}

但是这种方法会运行大量的 SQL 查询。如何使用预先加载来减少查询次数?

【问题讨论】:

    标签: php laravel eager-loading


    【解决方案1】:

    怎么样

    $user = Auth::user();
    $recipesFriends = $user->friends()->with('friends.recipes')->get();
    $recipesCookbooks = $user->with('followedCookbooks')->with('followedCookbooks.recipes')->get();
    

    如果你想更进一步,你可以看看这个答案:How to list out all items in a nested table in Laravel

    【讨论】:

    • 我使用分析器检查正在运行的查询。 $recipesFriends 的第二行运行了 4 个查询,其中一个是 select * from users。我永远不希望这个查询运行,因为当有很多用户注册时它会返回一个巨大的数据集。所以我稍微修改了你的方法并使用了:$recipesFriends = $user->friends()->with('friends.recipes')->get(); 这消除了select * from users 查询。谢谢!
    【解决方案2】:

    你可以试试这个:

    $userData = Auth::user()->load('cookbook.recipes')
                            ->load('friends.cookbook.recipes');
    

    如果你想在不同的变量中加载朋友的食谱,那么你可以试试这个:

    $userData = Auth::user()->load('cookbook.recipes')
                            ->load('friends.cookbook.recipes');
    $friendsData = $userData->friends;
    

    【讨论】:

      猜你喜欢
      • 2015-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-28
      • 2013-03-27
      • 2021-04-23
      相关资源
      最近更新 更多