Uzyskaj określone kolumny za pomocą funkcji „With ()” w Laravel Eloquent


197

Mam dwa stoły Useri Post. Jeden Usermoże mieć wiele postsi jeden postnależący do tylko jednego user.

W moim Usermodelu mam hasManyrelację ...

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

A w moim postmodelu mam belongsTorelację ...

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

Teraz chcę połączyć te dwie tabele za pomocą, Eloquent with()ale chcę konkretnych kolumn z drugiej tabeli. Wiem, że mogę korzystać z Konstruktora zapytań, ale nie chcę.

Kiedy w Postmodelu piszę ...

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

Uruchamia następujące zapytania ...

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

Ale chcę to ...

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

Kiedy używam ...

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

Zwraca tylko kolumnę z pierwszej tabeli. Chcę konkretnych kolumn przy użyciu with()z drugiej tabeli. Jak mogę to zrobić?

Odpowiedzi:


347

Znalazłem rozwiązanie. Można to zrobić, przekazując closurefunkcję with()jako drugi indeks tablicy, takiej jak

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

Wybierze tylko idiz usernameinnej tabeli. Mam nadzieję, że to pomoże innym.


Pamiętaj, że klucz podstawowy (w tym przypadku id) musi być pierwszym parametrem w $ query-> select (), aby faktycznie pobrać niezbędne wyniki. *


1
To dziwne, nie mogłem tego uruchomić. Jak tylko się dodałem $query->select('id','username');, otrzymywałemTrying to get property of non-object
user1669496

5
Dziwne! nadal zwraca wszystkie pola użytkownika. @AwaisQarni
justin

2
Dziękujemy za udostępnienie tego. Gdzie odkryłeś tę możliwość? Nie znalazłem tego w dokumentacji Laravela.
Symen Timmermans

81
Dla tych, którzy to widzą, pamiętaj, że klucz podstawowy ( idw tym przypadku) jest niezbędny, $query->select()aby faktycznie pobrać niezbędne wyniki. Pominąłem to w moim kodzie i nie mogłem zrozumieć, dlaczego nie znalazł żadnych wyników. Głupi ja! Mam nadzieję, że pomoże to każdemu, kto ma ten sam problem
Azirius

4
świetnie, wystarczy dodać klucz obcy, tutaj jego post_id, w przeciwnym razie wynik będzie pusty. Wspomnienie klucza obcego jest tutaj ważne. Dzięki :)
Hashaam Ahmed

102

Możesz to zrobić w ten sposób, ponieważ Laravel 5.5:

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

Dbaj o idpole i foreign keysjak stwierdzono w dokumentach :

Korzystając z tej funkcji, zawsze należy dołączyć kolumnę id i odpowiednie kolumny klucza obcego do listy kolumn, które chcesz pobrać.

Na przykład, jeśli użytkownik należy do zespołu i ma team_idkolumnę jako klucz obcy, wówczas $post->user->teamjest pusty, jeśli nie określono team_id

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

13
Nie zapomnij podać klucza obcego (zakładając, że tutaj jest post_id), aby rozwiązać relację, w przeciwnym razie otrzymasz puste wyniki dla relacji.
Hashaam Ahmed

2
To naprawdę powinna być wybrana odpowiedź. Działa jak urok :)
Graham,

@Adam, to ograniczy kolumny w tabeli podrzędnej, jak mogę ograniczyć kolumny z tabeli Tabela nadrzędna wraz z tabelą podrzędną?
Sodium

@GauravGenius wszystko, co chcesz ograniczyć od parant belogns w get()metodziePost::with('user:id,username')->get(['age', 'color']);
Adam

82

W twoim Postmodelu

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

Pierwotny kredyt trafia do Laravel Eager Loading - Załaduj tylko określone kolumny


14
Ale ta relacja sprawi, że będzie tak jak na stałe. W każdych warunkach zawsze zwrócą mi te dwa pola. Może się zdarzyć, że potrzebuję więcej pól w niektórych innych sytuacjach
Awais Qarni,

Następnie musisz użyć konstruktora zapytań.
user1669496,

5
To powinna być zaakceptowana odpowiedź. To jest właściwy sposób, aby to zrobić.
BugHunterUK

1
Czy jest na to sposób w wersji Laravel 5.3? Wydaje mi się, że zmienili to ... znowu .... a teraz, gdy próbuję z takim podejściem, staje się zerowy
Andre F.

Minęło trochę czasu, ale możesz dodać $fieldsparametr.
JordyvD

69

Kiedy idziesz w drugą stronę (hasMany):

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

Nie zapomnij dołączyć klucza obcego (zakładając, że w tym przykładzie jest to user_id), aby rozwiązać relację, w przeciwnym razie uzyskasz zerowe wyniki dla relacji.


6
Tak, dokładnie: „Nie zapomnij dołączyć klucza obcego (zakładając, że w tym przykładzie jest to user_id)”
aqingsao

powinieneś dołączyć kolumnę określającą relację w wybranych polach, w tym przypadku user_id
alimfazeli

Miło złapać brata.
Shahrukh Anwar,

niesamowite bracie, że użycie klucza obcego jest naprawdę ważne, na szczęście widziałem twojego ans, inaczej podrapałbym się w głowę przez wiele godzin. Dzięki!
Hashaam Ahmed

34

W Laravel 5.7 możesz wywoływać określone pola w ten sposób

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

Ważne jest, aby dodać foreign_keypole w zaznaczeniu.


11
nie zapomnij dodać pola klucza obcego
hendra1

2
Nie zapomnij zauważyć komentarza @ hendra1, wszystkie pola klucza obcego są również niezbędne wraz z kluczem podstawowym, w przeciwnym razie otrzymasz pustą kolekcję. Koleś oszczędził mi czas. Dzięki
Rajesh Vishnani,

14

W twoim Postmodelu:

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

Teraz możesz użyć $post->userWithName


2
Naprawdę? Dla mnie to po prostu nic nie zwraca, tzn. Że je psuje?
Sjwdavies

12

Jeśli chcesz uzyskać określone kolumny za pomocą with()elarquent laravela, możesz użyć kodu jak poniżej, na który pierwotnie odpowiedział @Adam w swojej odpowiedzi tutaj w odpowiedzi na to samo pytanie:

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

Użyłem tego w moim kodzie, ale dawało mi to błąd 1052: Column 'id' in field list is ambiguous, więc jeśli macie również ten sam problem

Następnie, aby go rozwiązać, musisz podać nazwę tabeli przed kolumną id w with()metodzie, jak poniżej :

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

Zwraca dla mnie wartość null, ale wcześniej nie wiedziałem, że to możliwe! Ok, więc opublikowałem przedwcześnie, ale znalazłem wynik. Aby użyć tej metody (wygląda na znacznie czystszą), musisz dołączyć link relacji, na przykład kolumnę identyfikatora podczas pobierania danych. Bez tego specyfikatora otrzymasz zerowy zwrot.
Adsy2010

tak @ Adsy2010, aby uzyskać powiązane dane relacji, musisz również uzyskać kolumnę identyfikatora lub klucz podstawowy lub inny identyfikator odpowiedzialny za tę relację.
Haritsinh Gohil

10

Natknąłem się na ten problem, ale z drugą warstwą powiązanych obiektów. Odpowiedź @Awais Qarni utrzymuje się wraz z włączeniem odpowiedniego klucza obcego do zagnieżdżonej instrukcji select. Tak jak identyfikator jest wymagany w pierwszej zagnieżdżonej instrukcji select, aby odwoływać się do powiązanego modelu, tak klucz obcy jest wymagany do odniesienia do drugiego stopnia powiązanych modeli; w tym przykładzie model firmy.

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

Ponadto, jeśli chcesz wybrać określone kolumny z modelu Post, musisz dołączyć kolumnę user_id do instrukcji select, aby móc się do niej odwoływać.

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

4

Zauważ, że jeśli potrzebujesz tylko jednej kolumny z tabeli, użycie „list” jest całkiem przyjemne. W moim przypadku pobieram ulubione artykuły użytkownika, ale chcę tylko identyfikatora artykułu:

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

Zwraca tablicę identyfikatorów, np .:

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

zwraca kolekcję!
Giovanni Far,

jeśli chcesz tablicy, to zadzwoń toArray()!!! $user->favourites->lists('id')->toArray();
Giovanni Far

Zapytanie nadal otrzyma inne kolumny, ponieważ metoda list () po prostu zmienia tablicę wyników, więc jeśli potrzebujesz tylko „id” z tej tabeli, możesz podać go w zapytaniu. Zawsze dobrze jest pamiętać o wydajności podczas wykonywania zapytań. Miłego kodowania!
Ervin Llojku

-1 $user->favouritespowróci Collectionz wybranymi wszystkimi polami. Prawidłowe stosowanie jest: $user->favourites()->lists('id').
Wallace Maxters

Wybór wszystkiego, aby później użyć filtrowania PHP, jest złym pomysłem. Najlepiej jest używać tylko potrzebnych pól w zapytaniu. Ważne jest, aby znać różnicę między Query\Builder::listsmetodą a Collection::listsmetodą.
Wallace Maxters

1

Możesz także określić kolumny w pokrewnym modelu w momencie dostępu do niego.

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


0

Teraz możesz użyć pluckmetody na Collectioninstancji:

Zwróci tylko uuidatrybutPost model

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

0

Spróbuj z warunkami.

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.