Laravel Eloquent: come ottenere solo determinate colonne da tabelle unite


102

Ho 2 tabelle unite in Eloquent, ovvero temi e utenti.

modello del tema:

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

modello utente:

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

La mia chiamata api eloquente appare come di seguito:

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

Che restituisce tutte le colonne dal tema (va bene) e tutte le colonne dall'utente (non va bene). Ho solo bisogno della colonna "nome utente" dal modello utente, come posso limitare la query a questo?


Sto eseguendo un'attività simile, posso sapere se utilizzo il Responsetipo di classe che devo importare?
Agnes Palit,

Risposte:


103

Cambia il tuo modello per specificare quali colonne vuoi selezionare:

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

E non dimenticare di includere la colonna a cui ti unisci.


6
ottima risposta, anche il suggerimento sull'inclusione della colonna join mi ha fatto risparmiare un sacco di tempo!
greatwitenorth

E se in alcuni posti avessi bisogno solo dell'ID invece dell'ID e del nome utente? Devi ancora selezionare entrambi?
Darius.V

Salve, la funzione di selezione ha la stessa funzione nel generatore di query del modello?
Gokigooooks

4
Non penso che sia un buon approccio. Sarà una sorta di hard coding dei nomi delle colonne. Tutti i luoghi restituiranno solo queste colonne. In qualche altra API, potrei aver bisogno di altre colonne, quindi non funzionerà qui. Penso che usare QueryBuilder sia l'opzione qui.
Aman Sura

2
Questo è un approccio drammatico in quanto accadrà ogni volta che effettui la chiamata in avanti. Credo che la risposta di Sajjad Ashraf sia quella a cui la maggior parte delle persone sarà interessata.
MMMTroy

37

Per Laravel> = 5.2

Usa il metodo -> pluck ()

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

Se desideri recuperare un array contenente i valori di una singola colonna, puoi utilizzare il metodo pluck


Per Laravel <= 5.1

Usa il metodo -> lists ()

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

Questo metodo restituirà una matrice di titoli di ruolo. Puoi anche specificare una colonna chiave personalizzata per l'array restituito:


2
Questa non è davvero una risposta alla domanda (che riguardava specificamente i join / relazioni).
orrd

30

Puoi fornire un array di campi nel parametro get in questo modo:

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

AGGIORNAMENTO (per Laravel 5.2) Dai documenti , puoi farlo:

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

2
Ho provato questo e mostra un errore SQLSTATE[42S22]: Column not founded è SQL non include la tabella nel file with. Lo sql che appare sull'errore è "SELECT fk_table.column1 FROM main_table".
Michel Ayres

1
È "users.username" (non "user.username"). Il codice nella risposta funzionerà se i nomi di tabella e colonna corrispondono al database effettivo. Questo è lo svantaggio di questa soluzione, sta costruendo una query SQL piuttosto che usare Eloquent, quindi i nomi devono corrispondere alle tabelle e alle colonne del database effettivo.
orrd

22

Lo so, chiedi Eloquent ma puoi farlo con Fluent Query Builder

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

16

Ecco come lo faccio

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

La prima risposta di user2317976 non ha funzionato per me, sto usando laravel 5.1


2
Risposta aggiornata = utile!
thesunneversets

Grazie. Funziona bene per me. Devo aggiungere la chiave esterna nell'istruzione select come hai fatto con "id" altrimenti restituisce null.
Iman Sedighi

Tuttavia, questo recupera ancora un campo "pivot" per ogni risultato, contenente entrambi gli ID (post_id e category_id) giusto? Come posso ottenerlo?
mayid

1
@mayid puoi provare ad aggiungere pivotalla serie $ hidden di Post Modelprotected $hidden = ['pivot']
Sajjad Ashraf

Questa è la soluzione migliore (supponendo che tu stia utilizzando una versione abbastanza moderna di Laravel)
orrd

11

Un'altra opzione consiste nell'utilizzare la $hiddenproprietà sul modello per nascondere le colonne che non si desidera visualizzare. È possibile definire questa proprietà al volo o impostare i valori predefiniti sul modello.

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

Ora la password degli utenti verrà nascosta quando restituisci la risposta JSON.

Puoi anche impostarlo al volo in modo simile.

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

2
in Laravel 4.2 ottengo 'Impossibile accedere alla proprietà protetta Utente :: $ nascosto' quando provo a impostarlo dinamicamente.
mtmacdonald

1
non dovrebbe essere static.
StackOverflowed

@StackOverflowed, presumo che tu non abbia prestato attenzione all'età di questa domanda / risposta e che si riferisse a Laravel 3.
Jason Lewis

10

Utilizzo con l'impaginazione

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

6

user2317976 ha introdotto un ottimo modo statico per selezionare le colonne delle tabelle correlate.

Ecco un trucco dinamico che ho trovato in modo da poter ottenere quello che vuoi quando usi il modello:

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

Ho appena scoperto che questo trucco funziona bene anche con load (). Questo è molto conveniente.

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

Assicurati di includere anche la chiave della tabella di destinazione altrimenti non sarà in grado di trovarla.


6

Per di qua:

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

Per favore, spiega sempre la tua risposta.
Rohit Gupta

Ho avuto un problema simile, questo è il modo più intelligente finora! Questa risposta è sottovalutata!
eldblz

Questa è la stessa risposta che era già stata precedentemente presentata da Sajjad Ashraf.
orrd

5

So che questa è una vecchia domanda, ma se stai costruendo un'API, come fa l'autore della domanda, usa trasformatori di output per eseguire tali attività.

Transofrmer è un livello tra il risultato effettivo della query del database e un controller. Consente di controllare e modificare facilmente ciò che verrà visualizzato in output per un utente o un consumatore API.

Consiglio Fractal come solida base per il tuo livello di trasformazione dell'output. Puoi leggere la documentazione qui .



4

Su Laravel 5.5, il modo più pulito per farlo è:

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

Aggiungi due punti e i campi che desideri selezionare separati da una virgola e senza spazi tra di loro.


Sai come possiamo recuperare una colonna specifica della tabella correlata quando si utilizza l'impaginazione.
Daniyal Nasir

2

Utilizzando il modello:

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

Utilizzo di Query Builder:

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

0

Se ho capito bene ciò che viene restituito va bene, tranne per il fatto che vuoi vedere solo una colonna. In tal caso, questo di seguito dovrebbe essere molto più semplice:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.