Отримайте конкретні стовпці, використовуючи функцію «З ()» у красномовному Laravel


198

У мене дві таблиці, Userі Post. Один Userможе бути багато , postsі один postналежить тільки один user.

У моїй Userмоделі я маю hasManyвідношення ...

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

І в моїй postмоделі я маю belongsToвідношення ...

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

Тепер я хочу приєднати ці дві таблиці за допомогою, Eloquent with()але хочу конкретних стовпців з другої таблиці. Я знаю, що можу використовувати Builder Query, але цього не хочу.

Коли в 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()з другої таблиці. Як я можу це зробити?

Відповіді:


348

Ну я знайшов рішення. Це можна зробити одним, передавши closureфункцію with()як другий індекс масиву, як

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

Він вибере лише idта usernameз іншої таблиці. Я сподіваюся, що це допоможе іншим.


Пам’ятайте, що первинний ключ (id в цьому випадку) повинен бути першим парам у $ query-> select (), щоб фактично отримати необхідні результати. *


2
Як це не дивно, я не міг змусити це працювати. Як тільки я додав $query->select('id','username');, я отримувавTrying to get property of non-object
user1669496

5
Дивно! як і раніше повертає всі поля користувача. @AwaisQarni
justin

2
Дякуємо, що поділилися цим. Де ви виявили таку можливість? Я не знайшов цього в документах Laravel.
Симен Тіммерманс

82
Для тих, хто бачить це, пам’ятайте, що первинний ключ ( idу даному випадку) необхідний у тому, $query->select()щоб фактично отримати необхідні результати. Я пропустив це у своєму коді і не зміг зрозуміти, чому це не знайде результатів. Дурний мене! Сподіваюся, це допомагає будь-кому іншому з тією ж проблемою
Азірій

4
чудово, просто потрібно додати зовнішній ключ, тут його post_id інакше результат буде порожнім. Тут важливо згадати зовнішній ключ. Дякую :)
Хашаам Ахмед

105

Ви можете це зробити так, як Laravel 5.5:

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

Догляд за idполем і foreign keysяк зазначено в документах :

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

Наприклад, якщо користувач належить до команди і має team_idстовпчик із зовнішнім ключем, він $post->user->teamпорожній, якщо ви не вказуєте team_id

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

13
Не забудьте включити зовнішній ключ (якщо припустити, що це post_id тут) для врегулювання відносин, інакше ви отримаєте порожні результати для свого відносини.
Хашаам Ахмед

2
Це справді має бути обрана відповідь. Працює як шарм :)
Грем

@Adam, Це обмежить стовпці в дочірній таблиці, як я можу обмежити стовпці з таблиці батьківська таблиця разом із дочірньою таблицею?
Натрій

@GauravGenius все, що ви хочете обмежити від парант-білонів get()методомPost::with('user:id,username')->get(['age', 'color']);
Адам

82

У вашій Postмоделі

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

Оригінальний кредит припадає на Laravel Eager Loading - завантажуйте лише конкретні стовпці


14
Але це відношення зробить це так само, як жорстке кодування. За будь-якого стану, він завжди поверне мені ці два поля. Може статися, що мені потрібно більше полів у деяких інших ситуаціях
Awais Qarni

Тоді потрібно скористатися конструктором запитів.
користувач1669496

5
Це має бути прийнятою відповіддю. Це правильний спосіб зробити це.
BugHunterUK

1
Чи є спосіб це зробити у версії Laravel 5.3? Я думаю, що вони змінили його ... знову .... і тепер воно повертається до нуля, коли я намагаюся з таким підходом
Андре Ф.

Минув деякий час, але ви можете додати $fieldsпараметр.
JordyvD

69

Коли ви йдете іншим шляхом (hasMany):

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

Не забудьте включити зовнішній ключ (припустимо, що це User_id у цьому прикладі), щоб вирішити відносини, інакше ви отримаєте нульові результати для свого відносини.


6
Так, саме "Не забудьте включити іноземний ключ (припустимо, що це user_id у цьому прикладі)"
aqingsao

ви повинні включити стовпчик, який визначає ваші стосунки у вибраних полях, у цьому випадку user_id
alimfazeli

Гарний спійманий брат.
Шахрух Анвар

диво-брате, що використання іноземного ключа дуже важливо, пощастило, що я бачив ваші анси, інакше я б почесав голову годинами хаха. Спасибі людино!
Хашаам Ахмед

35

У Laravel 5.7 ви можете викликати подібне поле

$users = App\Book::with('author:id,name')->get();

Важливо додати foreign_keyполе у ​​виборі.


12
не забудьте додати поле іноземного ключа
hendra1

2
Не забудьте помітити коментар @ hendra1, усі поля іноземних ключів також необхідні разом з первинним ключем, інакше ви отримаєте порожню колекцію. Чувак врятував мій час. Спасибі
Раджеш Вішнані

14

У вашій Postмоделі:

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

Тепер ви можете використовувати $post->userWithName


2
Дійсно? Для мене це просто нічого не повертає, тобто порушує?
Sjwdavies

12

Якщо ви хочете отримати конкретні стовпці, використовуючи with()красномовний ларавел, тоді ви можете використовувати код, як показано нижче, на який спочатку @Adam відповів у своїй відповіді тут, відповідаючи на це те саме питання:

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

Так що я використовував його в своєму коді, але він давав мені помилку 1052: Column 'id' in field list is ambiguous, тому якщо ви, хлопці, також зіткнулися з тією ж проблемою

Потім для її вирішення потрібно вказати ім'я таблиці перед стовпцем id вwith() методі, як показано нижче коду :

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

Це повертає нульове значення для мене, але я не знав, що це було можливо раніше! Гаразд, тому я розмістив прематурлі, але я знайшов результат. Щоб використовувати цей метод (виглядає набагато чистіше), ви повинні включати зв'язок зв'язку, наприклад стовпчик ідентифікатора, коли витягуєте дані. Без цього специфікатора ви отримуєте нульове повернення.
Adsy2010

так @ Adsy2010, для отримання даних про пов’язані стосунки вам також потрібно отримати стовпчик ідентифікатора або первинний ключ або той, який ідентифікатор відповідає за ці відносини.
Харіцин Гохіль

10

Я зіткнувся з цим питанням, але вже з другим шаром пов’язаних об'єктів. Відповідь @Awais Qarni відповідає включенню відповідного зовнішнього ключа у вкладений оператор select. Так само, як ідентифікатор необхідний в першому вкладеному операторі вибору для посилання на пов'язану модель, зовнішній ключ необхідний для посилання на другий ступінь пов'язаних моделей; у цьому прикладі модель компанії.

Post::with(['user' => function ($query) {
        $query->select('id','company_id', 'username');
    }, 'user.company' => function ($query) {
        $query->select('id', 'name');
    }])->get();

Крім того, якщо ви хочете вибрати конкретні стовпці з моделі публікації, вам потрібно буде включити стовпець user_id у оператор select, щоб посилатися на нього.

Post::with(['user' => function ($query) {
        $query->select('id', 'username');
    }])
    ->select('title', 'content', 'user_id')
    ->get();

4

Зауважте, що якщо вам потрібен лише один стовпець із таблиці, то використання "списків" - це дуже приємно. У моєму випадку я отримую улюблені статті користувача, але я хочу лише ідентифікатори статті:

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

Повертає масив ідентифікаторів, наприклад:

Array
(
    [0] => 3
    [1] => 7
    [2] => 8
)

повертає колекцію!
Джованні Далекий

якщо ви хочете масив, тоді телефонуйте toArray()!!! $user->favourites->lists('id')->toArray();
Джованні Далекий

Запит все одно отримає інші стовпці, оскільки метод list () просто змінює масив результатів, тож якщо вам просто потрібен 'id' з цієї таблиці, ви можете вказати його у запиті. Завжди є доброю звичкою мати на увазі продуктивність при виконанні запитів. Насолоджуйтесь кодування!
Ервіну Льойку

-1 $user->favouritesбуде поверненням Collectionіз усіма вибраними полями. Правильне використання: $user->favourites()->lists('id').
Wallace Maxters

Вибір усього для подальшого використання фільтрації PHP - погана ідея. Найкраще використовувати лише необхідні поля в запиті. Важливо знати різницю між Query\Builder::listsметодом і Collection::listsметодом.
Уоллес Макстерс

1

Ви також можете вказати стовпці відповідної моделі під час доступу до неї.

Post::first()->user()->get(['columns....']);


0

Тепер ви можете використовувати pluckметод на aCollection екземплярі:

Це поверне лише uuidатрибутPost model

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

0

Спробуйте з умовами.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.