Ottieni colonne specifiche usando la funzione "With ()" in Laravel Eloquent


198

Ho due tavoli Usere Post. Uno Userpuò avere molti postse uno postappartiene a uno solo user.

Nel mio Usermodello ho una hasManyrelazione ...

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

E nel mio postmodello ho una belongsTorelazione ...

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

Ora voglio unire queste due tabelle usando Eloquent with()ma voglio colonne specifiche dalla seconda tabella. So che posso usare Query Builder ma non voglio.

Quando nel Postmodello scrivo ...

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

Esegue le seguenti query ...

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

Ma quello che voglio è ...

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

Quando uso ...

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

Restituisce solo la colonna dalla prima tabella. Voglio colonne specifiche usando with()dalla seconda tabella. Come lo posso fare?

Risposte:


349

Bene ho trovato la soluzione. Si può fare uno passando una closurefunzione with()come secondo indice dell'array come

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

Seleziona solo ide usernamedall'altra tabella. Spero che questo possa aiutare gli altri.


Ricorda che la chiave primaria (id in questo caso) deve essere il primo parametro in $ query-> select () per recuperare effettivamente i risultati necessari. *


2
È strano, non sono riuscito a farlo funzionare. Non appena ho aggiunto $query->select('id','username');, stavo ricevendoTrying to get property of non-object
user1669496

5
Strano! restituisce comunque tutti i campi dell'utente. @AwaisQarni
justin

2
Grazie per aver condiviso questo. Dove hai scoperto questa possibilità? Non l'ho trovato nei documenti di Laravel.
Symen Timmermans,

82
Per coloro che lo vedono, ricorda che la chiave primaria ( idin questo caso) è necessaria $query->select()per recuperare effettivamente i risultati necessari. Ho omesso questo nel mio codice e non sono riuscito a capire perché non trovasse alcun risultato. Sciocco me! Spero che questo aiuti chiunque altro con lo stesso problema
Azirius,

4
ottimo, ho solo bisogno di aggiungere una chiave esterna, qui il suo post_id altrimenti il ​​risultato sarà vuoto. Menzionare la chiave esterna è importante qui. Grazie :)
Hashaam Ahmed,

106

Puoi farlo in questo modo da Laravel 5.5:

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

Cura del idcampo e foreign keyscome indicato nei documenti :

Quando si utilizza questa funzione, è necessario includere sempre la colonna ID e tutte le colonne chiave esterna pertinenti nell'elenco delle colonne che si desidera recuperare.

Ad esempio, se l'utente appartiene a un team e ha una team_idcolonna come chiave esterna, $post->user->teamè vuoto se non si specifica team_id

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

13
Non dimenticare di includere la chiave esterna (supponendo che sia post_id qui) per risolvere la relazione, altrimenti otterrai risultati vuoti per la tua relazione.
Hashaam Ahmed,

2
Questa dovrebbe davvero essere la risposta selezionata. Funziona come un incanto :)
Graham,

@Adam, questo limiterà le colonne nella tabella figlio, come posso limitare le colonne dalla tabella padre insieme alla tabella figlio?
Sodio

@GauravGenius tutto ciò che vuoi limitare dai parenti belogns nel get()metodoPost::with('user:id,username')->get(['age', 'color']);
Adam

82

Nel tuo Postmodello

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

Il credito originale va al caricamento desideroso di Laravel: carica solo colonne specifiche


14
Ma questa relazione lo renderà come hardcoded. In ogni condizione mi restituirà sempre questi due campi. Può succedere che ho bisogno di più campi in alcune altre situazioni
Awais Qarni,

Quindi è necessario utilizzare il generatore di query.
user1669496,

5
Questa dovrebbe essere la risposta accettata. Questo è il modo corretto di farlo.
BugHunterUK,

1
C'è un modo per farlo nella versione 5.3 di Laravel? Penso che lo abbiano cambiato ... di nuovo .... e ora restituisce null quando provo con questo approccio
Andre F.

È passato del tempo, ma è possibile aggiungere un $fieldsparametro.
JordyvD,

70

Quando vai nell'altra direzione (hasMany):

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

Non dimenticare di includere la chiave esterna (supponendo che sia user_id in questo esempio) per risolvere la relazione, altrimenti otterrai zero risultati per la tua relazione.


6
Sì, esattamente, "Non dimenticare di includere la chiave esterna (supponendo che sia user_id in questo esempio)"
aqingsao,

dovresti includere la colonna che definisce la tua relazione nei campi selezionati, in questo caso
user_id

Bel fratello.
Shahrukh Anwar,

fantastico fratello, che l'uso della chiave esterna è davvero importante, fortunatamente ho visto i tuoi ans altrimenti mi sarei grattato la testa per ore lol. Grazie uomo!
Hashaam Ahmed,

35

In Laravel 5.7 puoi chiamare un campo specifico come questo

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

È importante aggiungere un foreign_keycampo nella selezione.


12
non dimenticare di aggiungere il campo chiave esterna
hendra1

2
Non dimenticare di notare il commento di @ hendra1, tutti i campi della chiave esterna sono anche necessari insieme alla chiave primaria, altrimenti otterrai una raccolta vuota. Amico mi ha risparmiato tempo. Grazie
Rajesh Vishnani il

14

Nel tuo Postmodello:

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

Adesso puoi usare $post->userWithName


2
Veramente? Per me questo non restituisce nulla, cioè lo rompe?
Sjwdavies,

12

Se vuoi ottenere colonne specifiche usando with()in laravel eloquent, puoi usare il codice come sotto, che originariamente risponde a @Adam nella sua risposta qui in risposta a questa stessa domanda:

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

Quindi l'ho usato nel mio codice ma mi stava dando errore 1052: Column 'id' in field list is ambiguous, quindi se anche voi state affrontando lo stesso problema

Quindi per risolverlo devi specificare il nome della tabella prima della colonna id nel with()metodo come sotto codice :

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

Questo restituisce null per me, ma non sapevo che prima fosse possibile! Ok, quindi ho pubblicato prematurley ma ho trovato un risultato. Per utilizzare questo metodo (sembra molto più pulito) è necessario includere il collegamento di relazione, ad esempio la colonna ID quando si estrae con i dati. Senza questo specificatore, si ottiene un ritorno nullo.
Adsy2010,

Sì @ Adsy2010, per ottenere i dati relativi alla relazione correlata devi anche ottenere la colonna ID o la chiave primaria o qualsiasi ID responsabile di quella relazione.
Haritsinh Gohil,

10

Mi sono imbattuto in questo problema ma con un secondo strato di oggetti correlati. La risposta di @Awais Qarni regge con l'inclusione della chiave esterna appropriata nell'istruzione select nidificata. Proprio come un ID è richiesto nella prima istruzione select nidificata per fare riferimento al modello correlato, la chiave esterna è necessaria per fare riferimento al secondo grado di modelli correlati; in questo esempio il modello aziendale.

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

Inoltre, se si desidera selezionare colonne specifiche dal modello Posta, è necessario includere la colonna user_id nell'istruzione select per fare riferimento a essa.

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

4

Nota che se hai solo bisogno di una colonna dalla tabella, usare 'list' è abbastanza bello. Nel mio caso sto recuperando gli articoli preferiti di un utente ma voglio solo gli ID articolo:

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

Restituisce una matrice di ID, ad esempio:

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

restituisce una collezione!
Giovanni Far,

se vuoi un array allora chiama toArray()!!! $user->favourites->lists('id')->toArray();
Giovanni Far

La query otterrà comunque le altre colonne perché il metodo list () modifica l'array dei risultati, quindi se hai solo bisogno dell '"id" da quella tabella potresti volerlo specificare nella query. È sempre una buona abitudine tenere a mente le prestazioni quando si eseguono query. Goditi la programmazione!
Ervin Llojku,

-1 $user->favouritesverrà restituito Collectioncon tutti i campi selezionati. L'uso corretto è: $user->favourites()->lists('id').
Wallace Maxters,

Selezionare tutto per utilizzare in seguito il filtro PHP è una cattiva idea. È consigliabile utilizzare solo i campi necessari in Query. È importante conoscere la differenza tra Query\Builder::listsmetodo e Collection::listsmetodo.
Wallace Maxters,

1

È inoltre possibile specificare colonne sul modello correlato al momento dell'accesso.

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


0

Ora puoi usare il pluckmetodo su Collectionun'istanza:

Questo restituirà solo l' uuidattributo diPost model

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

0

Prova con le condizioni.

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

-3
EmployeeGatePassStatus::with('user:id,name')->get();

2
Questa è la stessa sintassi di questa risposta (solo nomi diversi per modello e colonna)
barbsan
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.