Ich habe die Dokumentation und API für Laravel-Sammlungen überprüft, finde aber anscheinend nicht, wonach ich suche:
Ich möchte ein Array mit Modelldaten aus einer Sammlung abrufen, aber nur bestimmte Attribute erhalten.
Dh so etwas wie Users::toArray('id','name','email')
, wo die Sammlung tatsächlich alle Attribute für die Benutzer enthält, weil sie an anderer Stelle verwendet werden, aber an dieser bestimmten Stelle benötige ich ein Array mit Benutzerdaten und nur die angegebenen Attribute.
In Laravel scheint es dafür keinen Helfer zu geben? - Wie kann ich das am einfachsten machen?
Collection::implode()
. Es kann eine Eigenschaft nehmen und aus allen Objekten in der Sammlung extrahieren. Dies beantwortet diese Frage nicht genau, kann aber für andere nützlich sein, die wie ich von Google hierher gekommen sind. laravel.com/docs/5.7/collections#method-implodeAntworten:
Sie können dies mit einer Kombination vorhandener
Collection
Methoden tun . Es mag zunächst etwas schwierig sein, dem zu folgen, aber es sollte leicht genug sein, um zusammenzubrechen.// get your main collection with all the attributes... $users = Users::get(); // build your second collection with a subset of attributes. this new // collection will be a collection of plain arrays, not Users models. $subset = $users->map(function ($user) { return collect($user->toArray()) ->only(['id', 'name', 'email']) ->all(); });
Erläuterung
Erstens durchläuft die
map()
Methode im Grunde nur dasCollection
und übergibt jedes Element imCollection
an den übergebenen Rückruf. Der von jedem Aufruf des Rückrufs zurückgegebene WertCollection
erstellt den von dermap()
Methode generierten neuen Wert .collect($user->toArray())
baut nur ein neues, temporäresCollection
aus denUsers
Attributen.->only(['id', 'name', 'email'])
reduziert die temporäreCollection
auf nur die angegebenen Attribute.->all()
verwandelt das temporäreCollection
zurück in ein einfaches Array.Wenn Sie alles zusammenfügen, erhalten Sie "Geben Sie für jeden Benutzer in der Benutzersammlung ein Array mit nur den Attributen ID, Name und E-Mail zurück."
Laravel 5.5 Update
Laravel 5.5 hat
only
dem Modell eine Methode hinzugefügt , die im Grunde das Gleiche tut wie diecollect($user->toArray())->only([...])->all()
, sodass dies in 5.5+ leicht vereinfacht werden kann, um:// get your main collection with all the attributes... $users = Users::get(); // build your second collection with a subset of attributes. this new // collection will be a collection of plain arrays, not Users models. $subset = $users->map(function ($user) { return $user->only(['id', 'name', 'email']); });
Wenn Sie dies mit dem in Laravel 5.4 eingeführten "Messaging höherer Ordnung" für Sammlungen kombinieren , kann dies noch weiter vereinfacht werden:
// get your main collection with all the attributes... $users = Users::get(); // build your second collection with a subset of attributes. this new // collection will be a collection of plain arrays, not Users models. $subset = $users->map->only(['id', 'name', 'email']);
quelle
::get([ 'fields', 'array' ])
Verhalten von QueryBuilder zu emulieren . Grundsätzlich wäre es praktisch für "Dumps".$newArray = Arr::only($initialArray, [ 'id', 'name' /* allowed keys list */ ]);
$users->map->only(['column', ...])
Mit use
User::get(['id', 'name', 'email'])
wird eine Sammlung mit den angegebenen Spalten zurückgegeben. Wenn Sie daraus ein Array machen möchten, verwenden Sie einfachtoArray()
die folgendeget()
Methode:User::get(['id', 'name', 'email'])->toArray()
In den meisten Fällen müssen Sie die Sammlung nicht in ein Array konvertieren, da Sammlungen tatsächlich Arrays auf Steroiden sind und Sie über benutzerfreundliche Methoden zum Bearbeiten der Sammlung verfügen.
quelle
->get(['id', 'email', 'name'])
Abfrage ausführen, die die Datenbank nicht anfordert, aber eine neue Sammlung mit nur den ausgewählten Werten zurückgibt. Methoden wie Zupfen / Listen, Erhalten, Erste usw. haben sowohl in der Abfrage-Generatorklasse als auch in der Auflistungsklasse dieselben Namen.Die folgende Methode funktioniert auch.
$users = User::all()->map(function ($user) { return collect($user)->only(['id', 'name', 'email']); });
quelle
Ich habe jetzt eine eigene Lösung dafür gefunden:
1. Erstellt eine allgemeine Funktion zum Extrahieren bestimmter Attribute aus Arrays
Die folgende Funktion extrahiert nur bestimmte Attribute aus einem assoziativen Array oder einem Array von assoziativen Arrays (das letzte erhalten Sie, wenn Sie $ collection-> toArray () in Laravel ausführen).
Es kann folgendermaßen verwendet werden:
$data = array_extract( $collection->toArray(), ['id','url'] );
Ich benutze folgende Funktionen:
function array_is_assoc( $array ) { return is_array( $array ) && array_diff_key( $array, array_keys(array_keys($array)) ); } function array_extract( $array, $attributes ) { $data = []; if ( array_is_assoc( $array ) ) { foreach ( $attributes as $attribute ) { $data[ $attribute ] = $array[ $attribute ]; } } else { foreach ( $array as $key => $values ) { $data[ $key ] = []; foreach ( $attributes as $attribute ) { $data[ $key ][ $attribute ] = $values[ $attribute ]; } } } return $data; }
Diese Lösung konzentriert sich nicht auf die Auswirkungen auf die Leistung beim Durchlaufen der Sammlungen in großen Datenmengen.
2. Implementieren Sie das Obige über eine benutzerdefinierte Sammlung in Laravel
Da ich einfach
$collection->extract('id','url');
auf jedes Sammlungsobjekt zugreifen möchte , habe ich eine benutzerdefinierte Sammlungsklasse implementiert.Zuerst habe ich ein allgemeines Modell erstellt, das das Eloquent-Modell erweitert, aber eine andere Auflistungsklasse verwendet. Alle Ihre Modelle müssen dieses benutzerdefinierte Modell erweitern und nicht das eloquente Modell.
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model as EloquentModel; use Lib\Collection; class Model extends EloquentModel { public function newCollection(array $models = []) { return new Collection( $models ); } } ?>
Zweitens habe ich die folgende benutzerdefinierte Sammlungsklasse erstellt:
<?php namespace Lib; use Illuminate\Support\Collection as EloquentCollection; class Collection extends EloquentCollection { public function extract() { $attributes = func_get_args(); return array_extract( $this->toArray(), $attributes ); } } ?>
Schließlich sollten alle Modelle stattdessen Ihr benutzerdefiniertes Modell wie folgt erweitern:
<?php namespace App\Models; class Article extends Model { ...
Nun sind die Funktionen von Nr. 1 oben werden von der Sammlung ordentlich verwendet, um die
$collection->extract()
Methode verfügbar zu machen .quelle
Sie müssen definieren
$hidden
und$visible
Attribute. Sie werden global festgelegt (dh, es werden immer alle Attribute vom$visible
Array zurückgegeben).Unter Verwendung der Methode
makeVisible($attribute)
undmakeHidden($attribute)
Sie können dynamisch versteckt ändern und sichtbare Attribute. Mehr: Eloquent: Serialisierung -> Vorübergehende Änderung der Sichtbarkeit von Eigenschaftenquelle
Ich hatte ein ähnliches Problem, bei dem ich Werte aus einem großen Array auswählen musste, aber ich wollte, dass die resultierende Sammlung nur Werte eines einzelnen Werts enthält.
pluck()
könnte für diesen Zweck verwendet werden (wenn nur 1 Schlüsselelement erforderlich ist)Sie könnten auch verwenden
reduce()
. So etwas mit reduzieren:$result = $items->reduce(function($carry, $item) { return $carry->push($item->getCode()); }, collect());
quelle
Dies ist eine Fortsetzung des obigen patricus [Antwort] [1], jedoch für verschachtelte Arrays:
$topLevelFields = ['id','status']; $userFields = ['first_name','last_name','email','phone_number','op_city_id']; return $onlineShoppers->map(function ($user) { return collect($user)->only($topLevelFields) ->merge(collect($user['user'])->only($userFields))->all(); })->all();
quelle
DB::table('roles')->pluck('title', 'name');
Referenzen: https://laravel.com/docs/5.8/queries#retrieving-results (Suche nach Zupfen)
quelle
Dies scheint zu funktionieren, ist sich aber nicht sicher, ob es für die Leistung optimiert ist oder nicht.
$request->user()->get(['id'])->groupBy('id')->keys()->all();
Ausgabe:
array:2 [ 0 => 4 1 => 1 ]
quelle
$users = Users::get(); $subset = $users->map(function ($user) { return array_only(user, ['id', 'name', 'email']); });
quelle