Laravel Eloquent: So erhalten Sie nur bestimmte Spalten aus verknüpften Tabellen


101

Ich habe 2 verknüpfte Tabellen in Eloquent, nämlich Themen und Benutzer.

Themenmodell:

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

Benutzermodell:

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

Mein eloquenter API-Aufruf sieht wie folgt aus:

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

Dies gibt alle Spalten vom Thema zurück (das ist in Ordnung) und alle Spalten vom Benutzer (nicht in Ordnung). Ich benötige nur die Spalte "Benutzername" aus dem Benutzermodell. Wie kann ich die Abfrage darauf beschränken?


Ich arbeite an einer ähnlichen Aufgabe. Kann ich wissen, ob ich Responsewelche Art von Klasse verwende, die ich importieren muss?
Agnes Palit

Antworten:


103

Ändern Sie Ihr Modell, um anzugeben, welche Spalten ausgewählt werden sollen:

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

Und vergessen Sie nicht, die Spalte anzugeben, der Sie beitreten.


6
Tolle Antwort, auch der Tipp zum Einfügen der Join-Spalte hat mir eine Menge Zeit gespart!
Greatwitenorth

Was ist, wenn ich an einigen Stellen nur ID anstelle von ID und Benutzername benötige? Müssen Sie noch beide auswählen?
Darius.V

Hallo, hat die Auswahlfunktion dieselbe Funktion im Modellabfrage-Generator?
Gokigooooks

4
Ich denke nicht, dass es ein guter Ansatz ist. Es wird eine Art harte Codierung der Spaltennamen sein. Alle Orte geben nur diese Spalten zurück. In einer anderen API benötige ich möglicherweise weitere Spalten, damit dies hier nicht funktioniert. Ich denke, QueryBuilder ist hier die Option.
Aman Sura

2
Dies ist ein dramatischer Ansatz, da er jedes Mal auftritt, wenn Sie den Anruf weiterleiten. Ich glaube, Sajjad Ashrafs Antwort ist die, an der die meisten Menschen interessiert sein werden.
MMMTroy

37

Für Laravel> = 5.2

Verwenden Sie die Methode -> pluck ()

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

Wenn Sie ein Array abrufen möchten, das die Werte einer einzelnen Spalte enthält, können Sie die Zupfmethode verwenden


Für Laravel <= 5.1

Verwenden Sie die Methode -> lists ()

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

Diese Methode gibt ein Array von Rollentiteln zurück. Sie können auch eine benutzerdefinierte Schlüsselspalte für das zurückgegebene Array angeben:


2
Dies ist nicht wirklich eine Antwort auf die Frage (die sich speziell mit Verknüpfungen / Beziehungen befasste).
oder

30

Sie können im Parameter get wie folgt eine Reihe von Feldern angeben:

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

UPDATE (für Laravel 5.2) In den Dokumenten können Sie Folgendes tun:

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

2
Ich habe es versucht und es zeigt einen Fehler SQLSTATE[42S22]: Column not foundund SQL enthält die Tabelle nicht in der with. Die SQL, die im Fehler angezeigt wird, lautet "SELECT fk_table.column1 FROM main_table".
Michel Ayres

1
Es ist "users.username" (nicht "user.username"). Der Code in der Antwort funktioniert, wenn die Tabellen- und Spaltennamen mit Ihrer tatsächlichen Datenbank übereinstimmen. Das ist der Nachteil dieser Lösung: Sie erstellt eine SQL-Abfrage, anstatt Eloquent zu verwenden. Daher müssen die Namen mit Ihren tatsächlichen Datenbanktabellen und -spalten übereinstimmen.
oder

22

Ich weiß, Sie fragen nach Eloquent, aber Sie können es mit Fluent Query Builder tun

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

16

So mache ich es

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

Erste Antwort von user2317976 hat bei mir nicht funktioniert, ich benutze laravel 5.1


2
Aktuelle Antwort = nützlich!
Thesunneversets

Vielen Dank. Es funktioniert gut für mich. Ich muss den Fremdschlüssel in die select-Anweisung einfügen, wie Sie es mit 'id' getan haben, sonst gibt er null zurück.
Iman Sedighi

Dadurch wird jedoch immer noch ein "Pivot" -Feld für jedes Ergebnis abgerufen, das beide IDs (post_id und category_id) enthält, oder? Wie kann ich damit fahren?
Mayid

1
@mayid können Sie versuchen, pivotzu $ versteckt Array von Post Modelprotected $hidden = ['pivot']
Sajjad Ashraf

Dies ist die beste Lösung (vorausgesetzt, Sie verwenden eine ziemlich moderne Version von Laravel)
oder

11

Eine andere Möglichkeit besteht darin, die $hiddenEigenschaft des Modells zu verwenden, um die Spalten auszublenden, die Sie nicht anzeigen möchten. Sie können diese Eigenschaft im laufenden Betrieb definieren oder Standardeinstellungen für Ihr Modell festlegen.

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

Jetzt wird das Benutzerkennwort ausgeblendet, wenn Sie die JSON-Antwort zurückgeben.

Auf ähnliche Weise können Sie es auch im laufenden Betrieb einstellen.

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

2
In Laravel 4.2 wird "Ich kann nicht auf die geschützte Eigenschaft User :: $ hidden zugreifen" angezeigt, wenn ich versuche, dies dynamisch festzulegen.
Mtmacdonald

1
es sollte nicht sein static.
StackOverflowed

@StackOverflowed, ich nehme an, Sie haben nicht bemerkt, wie alt diese Frage / Antwort ist und dass sie sich auf Laravel 3 bezieht.
Jason Lewis

10

Verwendung mit Paginierung

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

6

user2317976 hat eine großartige statische Methode zur Auswahl der Spalten verwandter Tabellen eingeführt.

Hier ist ein dynamischer Trick, den ich gefunden habe, damit Sie mit dem Modell alles bekommen, was Sie wollen:

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

Ich habe gerade festgestellt, dass dieser Trick auch mit load () gut funktioniert. Das ist sehr praktisch.

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

Stellen Sie sicher, dass Sie auch den Schlüssel der Zieltabelle angeben, da er sonst nicht gefunden werden kann.


6

Diesen Weg:

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

Bitte erläutern Sie immer Ihre Antwort.
Rohit Gupta

Hatte ein ähnliches Problem, dies ist der bisher klügste Weg! Diese Antwort wird unterschätzt!
Eldblz

Dies ist die gleiche Antwort wie die Antwort, die Sajjad Ashraf bereits zuvor eingereicht hat.
5.

5

Ich weiß, dass dies eine alte Frage ist, aber wenn Sie eine API erstellen, wie es der Autor der Frage tut, verwenden Sie Ausgabetransformatoren, um solche Aufgaben auszuführen.

Transofrmer ist eine Schicht zwischen Ihrem tatsächlichen Datenbankabfrageergebnis und einem Controller. Es ermöglicht die einfache Steuerung und Änderung der Ausgabe an einen Benutzer oder einen API-Konsumenten.

Ich empfehle Fractal als solide Grundlage für Ihre Ausgabetransformationsebene. Die Dokumentation können Sie hier lesen .



4

Auf Laravel 5.5 ist dies am saubersten:

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

Sie fügen einen Doppelpunkt und die Felder, die Sie auswählen möchten, getrennt durch ein Komma und ohne Leerzeichen dazwischen hinzu.


Wissen Sie, wie wir bei Verwendung der Paginierung eine bestimmte Spalte einer verwandten Tabelle abrufen können?
Daniyal Nasir

2

Verwenden des Modells:

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

Verwenden des Abfrage-Generators:

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

0

Wenn ich das gut verstanden habe, ist das, was zurückgegeben wird, in Ordnung, außer dass Sie nur eine Spalte sehen möchten. Wenn ja, sollte dies unten viel einfacher sein:

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.