Laravel Eloquent: как получить только определенные столбцы из объединенных таблиц

83

У меня есть две объединенные таблицы в Eloquent, а именно темы и пользователи.

модель темы:

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

модель пользователя:

public function themes() {
  return $this->has_many('Theme');
}

My Eloquent api call выглядит следующим образом:

return Response::eloquent(Theme::with('user')->get());

Возвращает все столбцы из темы (это прекрасно) и все столбцы от пользователя (не совсем). Мне нужен только столбец "имя пользователя" из пользовательской модели, как я могу ограничить этот запрос?

Теги:
eloquent

14 ответов

90

Измените свою модель, чтобы указать, какие столбцы вы хотите выбрать:

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

И не забудьте включить столбец, в который вы входите.

  • 6
    отличный ответ, также совет о включении столбца соединения сэкономил мне массу времени!
  • 0
    Что если в некоторых местах мне нужен только идентификатор вместо идентификатора и имени пользователя? Все еще должны выбрать оба?
Показать ещё 3 комментария
33

Для Laravel >= 5.2

Используйте метод - > pluck()

$roles = DB::table('roles')->pluck('title');

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


Для Laravel <= 5.1

Используйте метод - > lists()

$roles = DB::table('roles')->lists('title');

Этот метод вернет массив названий ролей. Вы также можете указать собственный столбец ключей для возвращаемого массива:

  • 2
    Это не совсем ответ на вопрос (который был конкретно о соединениях / отношениях).
25

Вы можете указать массив полей в параметре get так:

return Response::eloquent(Theme::with('user')->get(array('user.username'));

UPDATE (для Laravel 5.2) Из docs вы можете сделать это:

$response = DB::table('themes')
    ->select('themes.*', 'users.username')
    ->join('users', 'users.id', '=', 'themes.user_id')
    ->get();
  • 2
    Я попытался это, и он показывает ошибку SQLSTATE[42S22]: Column not found и это SQL не включает таблицу в with . Sql, который появляется в сообщении об ошибке: «SELECT fk_table.column1 FROM main_table».
  • 2
    Да, user.username не работает.
Показать ещё 1 комментарий
19

Я знаю, вы просите Eloquent, но вы можете сделать это с помощью Fluent Query Builder

$data = DB::table('themes')
    ->join('users', 'users.id', '=', 'themes.user_id')
    ->get(array('themes.*', 'users.username'));
10

Вот как я это делаю

$posts = Post::with(['category' => function($query){
        $query->select('id', 'name');
      }])->get();

Первый ответ пользователя2317976 не сработал у меня, я использую laravel 5.1

  • 1
    Актуальный ответ = полезно!
  • 0
    Благодарю. Он отлично работает для меня. Я должен добавить внешний ключ в оператор выбора, как вы сделали с 'id', в противном случае он возвращает ноль.
Показать ещё 5 комментариев
10

Другой вариант - использовать свойство $hidden в модели, чтобы скрыть столбцы, которые вы не хотите отображать. Вы можете определить это свойство на лету или установить значения по умолчанию для своей модели.

public static $hidden = array('password');

Теперь пароль пользователя будет скрыт при возврате ответа JSON.

Вы также можете установить его на лету аналогичным образом.

User::$hidden = array('password');
  • 2
    в Laravel 4.2 я получаю «Не удается получить доступ к защищенному свойству User :: $ hidden» при попытке установить это динамически.
  • 1
    это не должно быть static .
Показать ещё 1 комментарий
8

Использование с разбивкой на страницы

$data = DB::table('themes')
->join('users', 'users.id', '=', 'themes.user_id')
->select('themes.*', 'users.username')
->paginate(6);
5

Этот способ:

Post::with(array('user'=>function($query){
    $query->select('id','username');
}))->get();
  • 0
    Пожалуйста, всегда объясните свой ответ.
  • 0
    Была похожая проблема, это самый умный путь до сих пор! Этот ответ недооценен!
Показать ещё 1 комментарий
5

user2317976 ввел отличный статический способ выбора столбцов связанных таблиц.

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

return Response::eloquent(Theme::with(array('user' => function ($q) {
    $q->addSelect(array('id','username'))
}))->get();

Я просто нашел, что этот трюк также хорошо работает с load(). Это очень удобно.

$queriedTheme->load(array('user'=>function($q){$q->addSelect(..)});

Убедитесь, что вы также включаете ключ целевой таблицы, иначе он не сможет его найти.

4

Я знаю, что это старый вопрос, но если вы создаете API, как автор вопроса, используйте выходные трансформаторы для выполнения таких задач.

Transofrmer - это слой между фактическим результатом запроса базы данных и контроллером. Это позволяет легко контролировать и изменять то, что будет выводиться пользователю или потребителю API.

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

3

В Laravel 4 вы можете скрыть определенные поля от возврата, добавив следующее в свою модель.

protected $hidden = array('password','secret_field');

http://laravel.com/docs/eloquent#converting-to-arrays-or-json

1

Использование модели:

Model::where('column','value')->get(['column1','column2','column3',...]);

Использование Query Builder:

DB::table('table_name')->where('column','value')->get(['column1','column2','column3',...]);
0

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

return Response::eloquent(Theme::with('user')->get(['username']));
-4

Отъезд, http://laravel.com/docs/database/eloquent#to-array

Вы должны быть в состоянии определить, какие столбцы вы не хотите отображать в api.

Ещё вопросы

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