Laravel Eloquent: Jak uzyskać tylko niektóre kolumny z połączonych tabel


102

Mam 2 połączone tabele w Eloquent, a mianowicie motywy i użytkowników.

model motywu:

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

model użytkownika:

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

Moje wywołanie Eloquent API wygląda jak poniżej:

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

Co zwraca wszystkie kolumny z motywu (to dobrze) i wszystkie kolumny od użytkownika (nie w porządku). Potrzebuję tylko kolumny „nazwa użytkownika” z modelu użytkownika, jak mogę ograniczyć zapytanie do tego?


Pracuję nad podobnym zadaniem, czy mogę wiedzieć, czy używam Responsejakiej klasy muszę zaimportować?
Agnes Palit

Odpowiedzi:


103

Zmień model, aby określić, które kolumny chcesz wybrać:

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

I nie zapomnij dołączyć kolumny, do której się przyłączasz.


6
świetna odpowiedź, a także wskazówka dotycząca dołączenia kolumny dołączania pozwoliła mi zaoszczędzić mnóstwo czasu!
greatwitenorth

Co jeśli w niektórych miejscach potrzebuję tylko identyfikatora zamiast identyfikatora i nazwy użytkownika? Nadal musisz wybrać oba?
Darius.V

Cześć, czy funkcja select ma tę samą funkcję w konstruktorze zapytań modelu?
Gokigooooks

4
Nie sądzę, żeby to było dobre podejście. Będzie to trochę trudne do zakodowania nazw kolumn. Wszystkie miejsca zwrócą tylko te kolumny. W innym interfejsie API może być potrzebne więcej kolumn, więc to nie zadziała. Myślę, że użycie QueryBuilder jest tutaj opcją.
Aman Sura

2
Jest to dramatyczne podejście, ponieważ będzie się pojawiać za każdym razem, gdy wykonasz połączenie do przodu. Wierzę, że odpowiedź Sajjada Ashrafa jest tą, którą większość ludzi będzie zainteresowana.
MMMTroy

37

Dla Laravel> = 5,2

Używać -> zrywać) ( metoda

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

Jeśli chcesz pobrać tablicę zawierającą wartości pojedynczej kolumny, możesz użyć metody pluck


Dla Laravel <= 5,1

Użyj -> list () metoda

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

Ta metoda zwróci tablicę tytułów ról. Możesz również określić niestandardową kolumnę klucza dla zwracanej tablicy:


2
To nie jest tak naprawdę odpowiedź na pytanie (które dotyczyło szczególnie łączenia / związków).
orrd

30

Możesz podać tablicę pól w parametrze get w następujący sposób:

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

AKTUALIZACJA (dla Laravel 5.2) Z poziomu dokumentacji możesz to zrobić:

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

2
Próbowałem tego i pokazuje błąd, SQLSTATE[42S22]: Column not founda jego SQL nie zawiera tabeli w with. SQL, który pojawia się w błędzie to „SELECT fk_table.column1 FROM main_table”.
Michel Ayres,

1
To „nazwa.użytkownika” (nie „nazwa.użytkownika”). Kod w odpowiedzi zadziała, jeśli nazwy tabel i kolumn są zgodne z rzeczywistą bazą danych. To wada tego rozwiązania, tworzy zapytanie SQL zamiast używać Eloquent, więc nazwy muszą pasować do rzeczywistych tabel i kolumn bazy danych.
orrd

22

Wiem, prosisz o Eloquent, ale możesz to zrobić za pomocą Fluent Query Builder

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

16

Tak to robię

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

Pierwsza odpowiedź użytkownika2317976 nie działa dla mnie, używam laravel 5.1


2
Aktualna odpowiedź = przydatna!
thesunneversets

Dzięki. U mnie działa dobrze. Muszę dodać klucz obcy w instrukcji select, tak jak w przypadku „id”, w przeciwnym razie zwraca wartość null.
Iman Sedighi,

Jednak to nadal pobiera pole „pivot” dla każdego wyniku, zawierające oba identyfikatory (post_id i category_id), prawda? Jak mogę go przejechać?
Mayid

1
@mayid, możesz spróbować dodać pivotdo $ ukrytej tablicy Post Modelprotected $hidden = ['pivot']
Sajjad Ashraf

To najlepsze rozwiązanie (zakładając, że używasz dość nowoczesnej wersji Laravel)
orrd

11

Inną opcją jest użycie $hiddenwłaściwości modelu w celu ukrycia kolumn, których nie chcesz wyświetlać. Możesz zdefiniować tę właściwość w locie lub ustawić wartości domyślne w modelu.

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

Teraz hasło użytkownika zostanie ukryte, gdy zwrócisz odpowiedź JSON.

Możesz również ustawić go w locie w podobny sposób.

User::$hidden = array('password');

2
w Laravel 4.2 otrzymuję komunikat „Nie można uzyskać dostępu do właściwości chronionych User :: $ hidden”, gdy próbuję ustawić to dynamicznie.
mtmacdonald

1
nie powinno static.
StackOverflowed

@StackOverflowed, zakładam, że nie zwróciłeś uwagi na to, ile lat ma to pytanie / odpowiedź i że dotyczyło to Laravel 3.
Jason Lewis

10

Używanie z paginacją

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

6

user2317976 wprowadził wspaniały statyczny sposób wybierania kolumn powiązanych tabel.

Oto dynamiczna sztuczka, którą znalazłem, dzięki której możesz uzyskać wszystko, co chcesz, używając modelu:

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

Właśnie odkryłem, że ta sztuczka działa również dobrze z load (). To bardzo wygodne.

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

Upewnij się, że dołączasz również klucz tabeli docelowej, w przeciwnym razie nie będzie w stanie go znaleźć.


6

Tą drogą:

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

Proszę zawsze wyjaśniać swoją odpowiedź.
Rohit Gupta

Miałem podobny problem, to jak dotąd najmądrzejszy sposób! Ta odpowiedź jest niedoceniana!
eldblz,

Jest to to samo, co odpowiedź, której wcześniej udzielił Sajjad Ashraf.
orrd

5

Wiem, że to stare pytanie, ale jeśli budujesz API, tak jak robi to autor pytania, użyj transformatorów wyjściowych do wykonywania takich zadań.

Transofrmer to warstwa między rzeczywistym wynikiem zapytania w bazie danych a kontrolerem. Pozwala w łatwy sposób kontrolować i modyfikować to, co ma być wyprowadzane dla użytkownika lub konsumenta API.

Polecam Fractal jako solidną podstawę twojej wyjściowej warstwy transformacji. Możesz przeczytać dokumentację tutaj .



4

W Laravel 5.5 najczystszym sposobem na to jest:

Theme::with('user:userid,name,address')->get()

Dodajesz dwukropek i pola, które chcesz wybrać, oddzielone przecinkiem i bez spacji między nimi.


Czy wiesz, jak możemy pobrać określoną kolumnę z powiązanej tabeli podczas korzystania z paginacji.
Daniyal Nasir

2

Korzystanie z modelu:

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

Korzystanie z Query Builder:

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

0

Jeśli dobrze to zrozumiałem, to, co jest zwracane, jest w porządku, chyba że chcesz zobaczyć tylko jedną kolumnę. Jeśli tak, to poniżej powinno być znacznie prostsze:

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

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.