Erhalten Sie bestimmte Spalten mit der Funktion "With ()" in Laravel Eloquent

196

Ich habe zwei Tische Userund Post. Man Userkann viele haben postsund man postgehört nur einem user.

In meinem UserModell habe ich eine hasManyBeziehung ...

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

Und in meinem postModell habe ich eine belongsToBeziehung ...

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

Jetzt möchte ich diese beiden Tabellen mit verbinden Eloquent with(), möchte aber bestimmte Spalten aus der zweiten Tabelle. Ich weiß, dass ich den Query Builder verwenden kann, möchte es aber nicht.

Wenn Postich im Modell schreibe ...

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

Es werden die folgenden Abfragen ausgeführt ...

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

Aber was ich will ist ...

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

Wenn ich benutze ...

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

Es wird nur die Spalte aus der ersten Tabelle zurückgegeben. Ich möchte bestimmte Spalten with()aus der zweiten Tabelle verwenden. Wie kann ich das machen?

Awais Qarni
quelle

Antworten:

345

Nun, ich habe die Lösung gefunden. Dies kann durch Übergabe einer closureFunktion with()als zweiter Index eines Arrays erfolgen

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

Es wird nur idund usernameaus einer anderen Tabelle ausgewählt. Ich hoffe das wird anderen helfen.


Denken Sie daran, dass der Primärschlüssel (in diesem Fall die ID) der erste Parameter in $ query-> select () sein muss, um die erforderlichen Ergebnisse tatsächlich abzurufen. *

Awais Qarni
quelle
1
Das ist seltsam, ich konnte das nicht zum Laufen bringen. Sobald ich hinzufügte $query->select('id','username');, bekam ichTrying to get property of non-object
user1669496
5
Seltsam! Gibt weiterhin alle Felder des Benutzers zurück. @ WaisQarni
Justin
2
Vielen Dank für das Teilen. Wo haben Sie diese Möglichkeit entdeckt? Ich habe das in den Laravel-Dokumenten nicht gefunden.
Symen Timmermans
79
Denken Sie für diejenigen, die dies sehen, daran, dass der Primärschlüssel ( idin diesem Fall) erforderlich ist $query->select(), um die erforderlichen Ergebnisse tatsächlich abzurufen. Ich habe dies in meinem Code weggelassen und konnte nicht herausfinden, warum keine Ergebnisse erzielt wurden. Wie dumm von mir! Hoffe, dies hilft allen anderen mit dem gleichen Problem
Azirius
4
großartig, ich muss nur einen Fremdschlüssel hinzufügen, hier ist seine post_id, sonst ist das Ergebnis leer. Das Erwähnen von Fremdschlüsseln ist hier wichtig. Danke :)
Hashaam Ahmed
102

Sie können es seit Laravel 5.5 so machen:

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

Pflege für das idFeld und foreign keyswie in den Dokumenten angegeben :

Wenn Sie diese Funktion verwenden, sollten Sie immer die ID-Spalte und alle relevanten Fremdschlüsselspalten in die Liste der Spalten aufnehmen, die Sie abrufen möchten.

Wenn der Benutzer beispielsweise zu einem Team gehört und eine team_idSpalte als Fremdschlüssel hat, $post->user->teamist diese leer, wenn Sie keine Angaben machen team_id

Post::with('user:id,username,team_id')->get();
Adam
quelle
13
Vergessen Sie nicht, den Fremdschlüssel (vorausgesetzt, er ist hier post_id) anzugeben, um die Beziehung aufzulösen. Andernfalls erhalten Sie leere Ergebnisse für Ihre Beziehung.
Hashaam Ahmed
2
Dies sollte wirklich die ausgewählte Antwort sein. Funktioniert wie ein Zauber :)
Graham
@Adam, Dies wird die Spalten in der untergeordneten Tabelle einschränken. Wie kann ich Spalten aus der übergeordneten Tabelle zusammen mit der untergeordneten Tabelle einschränken?
Natrium
@ GauravGenius alles, was Sie von Parant Belogns in der get()Methode einschränken möchtenPost::with('user:id,username')->get(['age', 'color']);
Adam
82

In Ihrem PostModell

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

Das ursprüngliche Guthaben geht an Laravel Eager Loading - Nur bestimmte Spalten laden

user1669496
quelle
14
Aber diese Beziehung wird es genauso machen wie fest codiert. In jedem Fall werden mir diese beiden Felder immer zurückgegeben. Es kann vorkommen, dass ich in einigen anderen Situationen mehr Felder benötige
Awais Qarni
Dann müssen Sie den Abfrage-Generator verwenden.
user1669496
5
Dies sollte die akzeptierte Antwort sein. Dies ist der richtige Weg.
BugHunterUK
1
Gibt es eine Möglichkeit, dies in der Laravel 5.3-Version zu tun? Ich denke, sie haben es geändert ... wieder ... und jetzt gibt es null zurück, wenn ich es mit diesem Ansatz versuche
Andre F.
Es ist schon eine Weile her, aber Sie könnten einen $fieldsParameter hinzufügen .
JordyvD
69

Wenn Sie in die andere Richtung gehen (hasMany):

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

Vergessen Sie nicht, den Fremdschlüssel (in diesem Beispiel vorausgesetzt, er ist user_id) anzugeben, um die Beziehung aufzulösen. Andernfalls erhalten Sie keine Ergebnisse für Ihre Beziehung.

Thijs
quelle
6
Ja, genau: "Vergessen Sie nicht, den Fremdschlüssel einzuschließen (vorausgesetzt, es handelt sich in diesem Beispiel um user_id)"
aqingsao
Sie sollten eine Spalte, die Ihre Beziehung definiert, in ausgewählte Felder einfügen, in diesem Fall user_id
alimfazeli
Netter Fangbruder.
Shahrukh Anwar
Super Bruder, die Verwendung von Fremdschlüsseln ist wirklich wichtig. Zum Glück habe ich deine Ans gesehen, sonst hätte ich mir stundenlang am Kopf gekratzt, lol. Danke, Mann!
Hashaam Ahmed
34

In Laravel 5.7 können Sie ein bestimmtes Feld wie dieses aufrufen

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

Es ist wichtig, foreign_keyder Auswahl ein Feld hinzuzufügen .

hendra1
quelle
11
Vergessen Sie nicht, das Fremdschlüsselfeld hinzuzufügen
hendra1
2
Vergessen Sie nicht, den Kommentar von @ hendra1 zu beachten. Alle Fremdschlüsselfelder sind neben dem Primärschlüssel ebenfalls erforderlich. Andernfalls erhalten Sie eine leere Sammlung. Alter hat mir Zeit gespart. Vielen Dank
Rajesh Vishnani
14

In Ihrem PostModell:

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

Jetzt können Sie verwenden $post->userWithName

Duy Hoang
quelle
2
"Ja wirklich?" Für mich gibt das einfach nichts zurück, dh es bricht es?
Sjwdavies
12

Wenn Sie bestimmte Spalten with()in laravel eloquent verwenden möchten, können Sie den folgenden Code verwenden, der ursprünglich von @Adam in seiner Antwort hier als Antwort auf dieselbe Frage beantwortet wurde:

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

Also habe ich es in meinem Code verwendet, aber es gab mir einen Fehler von 1052: Column 'id' in field list is ambiguous, also wenn ihr auch vor dem gleichen Problem steht

Um es zu lösen, müssen Sie den Tabellennamen vor der ID-Spalte in der with()Methode wie folgt angeben :

Post::with('user:user.id,username')->get();
Haritsinh Gohil
quelle
Dies gibt für mich null zurück, aber ich wusste vorher nicht, dass dies möglich ist! Ok, also habe ich vorzeitig gepostet, aber ich habe ein Ergebnis gefunden. Um diese Methode zu verwenden (sieht viel sauberer aus), müssen Sie den Beziehungslink einfügen, z. B. die ID-Spalte, wenn Sie die With-Daten abrufen. Ohne diesen Bezeichner erhalten Sie eine Null-Rückgabe.
Adsy2010
yeah @ Adsy2010, um verwandte Beziehungsdaten zu erhalten, müssen Sie auch die ID-Spalte oder den Primärschlüssel oder die ID abrufen, die für diese Beziehung verantwortlich ist.
Haritsinh Gohil
10

Ich bin auf dieses Problem gestoßen, aber mit einer zweiten Schicht verwandter Objekte. Die Antwort von @Awais Qarni gilt für die Aufnahme des entsprechenden Fremdschlüssels in die verschachtelte select-Anweisung. So wie in der ersten verschachtelten select-Anweisung eine ID erforderlich ist, um auf das verwandte Modell zu verweisen, muss der Fremdschlüssel auf den zweiten Grad verwandter Modelle verweisen. in diesem Beispiel das Unternehmensmodell.

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

Wenn Sie bestimmte Spalten aus dem Post-Modell auswählen möchten, müssen Sie außerdem die Spalte user_id in die select-Anweisung aufnehmen, um darauf zu verweisen.

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

Beachten Sie, dass die Verwendung von 'Listen' sehr hilfreich ist, wenn Sie nur eine Spalte aus der Tabelle benötigen. In meinem Fall rufe ich die Lieblingsartikel eines Benutzers ab, möchte aber nur die Artikel-IDs:

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

Gibt ein Array von IDs zurück, z.

Array
(
    [0] => 3
    [1] => 7
    [2] => 8
)
omar j
quelle
es gibt eine Sammlung zurück!
Giovanni Far
Wenn Sie ein Array wollen, dann rufen Sie an toArray()!!! $user->favourites->lists('id')->toArray();
Giovanni Far
Die Abfrage erhält weiterhin die anderen Spalten, da die list () -Methode nur das Ergebnisarray ändert. Wenn Sie also nur die 'id' aus dieser Tabelle benötigen, möchten Sie diese möglicherweise in der Abfrage angeben. Es ist immer eine gute Angewohnheit, bei Abfragen die Leistung im Auge zu behalten. Viel Spaß beim Codieren!
Ervin Llojku
-1 $user->favouriteswird Collectionmit allen ausgewählten Feldern zurückgegeben. Die richtige Verwendung ist : $user->favourites()->lists('id').
Wallace Maxters
Es ist eine schlechte Idee, alles auszuwählen, um später die PHP-Filterung zu verwenden. Es ist am besten, nur die benötigten Felder in Query zu verwenden. Es ist wichtig, den Unterschied zwischen Query\Builder::listsMethode und Collection::listsMethode zu kennen.
Wallace Maxters
1

Sie können zum Zeitpunkt des Zugriffs auch Spalten für das zugehörige Modell angeben.

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

Shreyansh Panchal
quelle
0

Jetzt können Sie die pluckMethode für eine CollectionInstanz verwenden:

Dies gibt nur das uuidAttribut von zurückPost model

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

Versuchen Sie es mit Bedingungen.

$id = 1;
Post::with(array('user'=>function($query) use ($id){
    $query->where('id','=',$id);
    $query->select('id','username');
}))->get();
Shirjeel Ahmed Khan
quelle
-3
EmployeeGatePassStatus::with('user:id,name')->get();
kush
quelle
1
Dies ist die gleiche Syntax wie in dieser Antwort (nur unterschiedliche Namen für Modell und Spalte)
Barbansan