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?

ralu
quelle
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.

user2317976
quelle
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:

Javi Stolz
quelle
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();
Melvin
quelle
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'));
Aykut
quelle
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

Sajjad Ashraf
quelle
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');
Jason Lewis
quelle
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);
Nufayl
quelle
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.

KinoP
quelle
6

Diesen Weg:

Post::with(array('user'=>function($query){
    $query->select('id','username');
}))->get();
Technische Daten
quelle
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 .

Armen Markossyan
quelle
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.

JoeGalind
quelle
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',...]);
srmilon
quelle
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']));
Kornel
quelle