2014-06-23 2 views
0

У меня есть модель User, модель Recipe и модель Cookbook.Laravel 4 eager loading

Пользователь может «владеть» множеством рецептов. (User -OneToMany- Рецепт)

Пользователь имеет «только одну» поваренную книгу. (User -OneToOne- Cookbook)

Рецепты, которыми владеет пользователь, принадлежат его Поваренной книге. Один рецепт может принадлежать многим Поваренной книге. (Рецепт обмена) (Поваренная книга -ManyToMany- Рецепт)

Многие пользователи могут ЛЮБИТЬ много рецептов. (User -ManyToMany- Рецепт)

Многие пользователи могут следить за многими поваренными книгами. (Пользователь -ManyToMany- Cookbook)

Один пользователь может иметь много друзей, которые пользователи (Пользователь -OneToMany- пользователя)


То, что я хочу сделать, это рецепты загрузки для вошедшего в пользователе.

Я хочу, чтобы загрузить рецепты, принадлежащие его друзьям и рецепты все кулинарные книги, вошедшего в систему пользователя в следующих.


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-запросов. Как использовать интенсивную загрузку для уменьшения количества запросов?

ответ

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

+0

Я использовал профилировщик для проверки запущенных запросов. Вторая строка для '$ recipesFriends' запускала 4 запроса, из которых один был' select * from users'. Я бы никогда не захотел, чтобы этот запрос выполнялся, потому что он возвратил бы огромный набор данных, когда было зарегистрировано много пользователей. Так я изменил свой метод немного и используется: '$ recipesFriends = $ user-> друзья() -> с ('friends.recipes') -> получить();' Это устранили 'выбрать * из запроса пользователя. Спасибо! –

+0

Редактирует мой ответ соответственно! –

0

Вы можете попробовать это:

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

Если вы хотите для загрузки рецептов друзей в другую переменную, вы можете попробовать:

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