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?

ralu
źródło
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.

user2317976
źródło
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:

Javi Stolz
źródło
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();
Melvin
źródło
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'));
aykut
źródło
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

Sajjad Ashraf
źródło
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');
Jason Lewis
źródło
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);
Nufayl
źródło
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źć.

KinoP
źródło
6

Tą drogą:

Post::with(array('user'=>function($query){
    $query->select('id','username');
}))->get();
Okular
źródło
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 .

Armen Markossyan
źródło
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.

JoeGalind
źródło
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',...]);
srmilon
źródło
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']));
Kornel
źródło