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.