Отримайте конкретні стовпці, використовуючи функцію «З ()» у красномовному 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.