Получить конкретные столбцы с помощью функции «With ()» в Laravel Eloquent

70

У меня есть две таблицы User и Post One User имеют много posts, а один Post принадлежит только одному User.

В моей модели User у меня есть отношение hasMany, подобное

public function post(){
        return $this->hasmany('post');
}

И в моей модели Post у меня есть отношение belongsTo как

public function user(){
        return $this->belongsTo('user');
}

Теперь я хочу объединить эти две таблицы, используя Eloquent with(), но хочу, чтобы определенные столбцы из второй таблицы. Я знаю, что могу использовать query Builder, но я не хочу этого использовать. Когда в модели Post я пишу

public function getAllPosts() {
        return Post::with('user')->get();
}

Он запускает следующие очереди

select * from `posts`
select * from `users` where `users`.`id` in (<1>, <2>)

Но я хочу

select * from `posts`
select id,username from `users` where `users`.`id` in (<1>, <2>)

Когда я использую

Post::with('user')->get(array('columns'....));

Он возвращает столбец только из первой таблицы. Я хочу, чтобы определенные столбцы использовали with() из второй таблицы. Как я могу это сделать?

Теги:
eloquent
orm

7 ответов

168
Лучший ответ

Ну, я нашел решение. Это можно сделать путем передачи функции closure в with() в качестве второго индекса массива типа

 Post::with(array('user'=>function($query){
        $query->select('id','username');
    }))->get();

Он выберет только id и username из другой таблицы. Надеюсь, это поможет другим.


Помните, что первичный ключ (id в этом случае) необходим в $query- > select() для фактического получения необходимых результатов.

  • 1
    Странно, я не мог заставить это работать. Как только я добавил в $query->select('id','username'); Trying to get property of non-object
  • 0
    @ user1669496 Вы определили отношения hasmany и belongsto к вашей модели ??
Показать ещё 13 комментариев
48

В вашей модели Post

public function user()
{
    return $this->belongsTo('User')->select(array('id', 'username'));
}

Оригинальный кредит отправляется Laravel Eager Loading - Загрузка только определенных столбцов

  • 9
    Но это отношение сделает его таким же жестко закодированным. При всех условиях он всегда вернет мне эти два поля. Может случиться так, что мне нужно больше полей в некоторых других ситуациях
  • 0
    Тогда вы должны использовать построитель запросов.
Показать ещё 5 комментариев
22

При движении другим способом (hasMany):

User::with(array('post'=>function($query){
        $query->select('id','user_id');
    }))->get();

Не забудьте включить внешний ключ (при условии, что он является user_id в этом примере), чтобы разрешить взаимосвязь, иначе вы получите нулевые результаты для своего отношения.

  • 2
    Да, именно: «Не забудьте включить внешний ключ (при условии, что в этом примере это user_id)»
  • 0
    Это работало только для меня!
Показать ещё 4 комментария
8

В вашей модели Post:

public function userWithName()
{
    return $this->belongsTo('User')->select(array('id', 'first_name', 'last_name'));
}

Теперь вы можете использовать $post->userWithName

  • 1
    В самом деле? Для меня это просто ничего не возвращает, т.е. это ломает?
  • 1
    Да, для меня это работает хорошо :)
4

Вы можете сделать это в Laravel 5.5:

Post::with('user:id,username')->get();

Уход за полем id, как указано в docs:

При использовании этой функции вы всегда должны включать столбец id в список столбцов, которые вы хотите получить.

  • 2
    Не забудьте включить внешний ключ (при условии, что это post_id здесь), чтобы разрешить отношение, иначе вы получите пустые результаты для вашего отношения.
3

Обратите внимание, что если вам нужен только один столбец из таблицы, то использование "списков" довольно хорошо. В моем случае я извлекаю любимые статьи пользователя, но мне нужен только идентификатор статьи:

$favourites = $user->favourites->lists('id');

Возвращает массив идентификаторов, например:

Массив (   [0] = > 3   [1] = > 7   [2] = > 8 )

  • 0
    это вернуть коллекцию!
  • 0
    если вы хотите массив, тогда вызовите toArray() !!! $user->favourites->lists('id')->toArray();
Показать ещё 3 комментария
-2

Теперь вы можете использовать метод pluck для экземпляра Collection:

Это вернет только атрибут uuid Post model

App\Models\User::find(2)->posts->pluck('uuid')
=> Illuminate\Support\Collection {#983
     all: [
       "1",
       "2",
       "3",
     ],
   }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню