API-Ressourcen
- Einführung
- Ressourcen generieren
- Ressourcensammlung
- Ressourcensammlung
- Benutzerdefinierte Basisressourcenklasse
- Metadaten hinzufügen
- Ressourcen schreiben
- Ressourcensammlung
- Verschachtelte Ressourcen umschließen
- Datenumbruch und Paging
- Paging
- Bedingte Attribute
- Daten bedingt zusammenführen
Eloquent: API Ressourcen
Einführung
beim Bauen API benötigen Sie oft eine Transformationsschicht, um Ihr Eloquent-Modell und die tatsächliche JSON-Antwort, die an den Benutzer zurückgegeben wird, zu verbinden. Mit den Ressourcenklassen von Laravel können Sie Modelle und Modellsammlungen intuitiver und einfacher in JSON konvertieren.
Ressourcen generieren
Sie können den Befehl
make:resource
Artisan verwenden, um eine Ressourcenklasse zu generieren. Standardmäßig werden generierte Ressourcen im Ordnerapp/Http/Resources
der Anwendung abgelegt. Ressourcen erben von der KlasseIlluminateHttpResourcesJsonJsonResource
:php artisan make:resource User
Ressourcensammlung
Zusätzlich zum Generieren von Ressourcen zum Konvertieren eines einzelnen Modells können Sie auch eine Ressourcensammlung zum Konvertieren einer Sammlung von Modellen generieren. Auf diese Weise können Sie Links und andere Metainformationen zu einer bestimmten Ressource in die Antwort einfügen.
Sie müssen beim Generieren von Ressourcen das Flag
--collection
hinzufügen, um eine Ressourcensammlung zu generieren. Alternativ können SieCollection
direkt in den Ressourcennamen einfügen, um Laravel anzugeben, dass eine Sammlung von Ressourcen generiert werden soll. Ressourcensammlungen erben von derIlluminateHttpResourcesJsonResourceCollection
-Klasse:php artisan make:resource Users --collection php artisan make:resource UserCollection
Konzeptübersicht
{tip} Dies ist eine Zusammenfassung von Ressourcen und Ressourcensammlungen Allgemeiner Überblick. Es wird dringend empfohlen, die anderen Abschnitte dieses Dokuments zu lesen, um Einblicke in die bessere Anpassung und Nutzung der Ressource zu erhalten.
Bevor wir uns damit befassen, wie Sie Ihre Ressourcen individuell schreiben, werfen wir zunächst einen Blick darauf, wie Sie Ressourcen in Laravel verwenden. Eine Ressourcenklasse stellt ein einzelnes Modell dar, das in das JSON-Format konvertiert werden muss. Jetzt haben wir zum Beispiel eine einfache
User
-Ressourcenklasse:<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class User extends JsonResource{ /** * 将资源转换成数组。 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, ]; } }
Jede Ressourcenklasse definiert eine
toArray
-Methode, die ein Array von Eigenschaften zurückgibt, die beim Senden einer Antwort in JSON konvertiert werden sollen. Beachten Sie hier, dass wir die Variable$this
direkt verwenden können, um auf die Modelleigenschaften zuzugreifen. Dies liegt daran, dass die Ressourcenklasse automatisch Eigenschaften und Methoden an das zugrunde liegende Modell weiterleitet, um einen einfachen Zugriff zu ermöglichen. Sie können definierte Ressourcen in Routen oder Controllern zurückgeben:use App\User; use App\Http\Resources\User as UserResource; Route::get('/user', function () { return new UserResource(User::find(1)); });
Ressourcensammlung
Sie können die Methode
collection
in Routen oder Controllern verwenden, um Ressourceninstanzen zu erstellen, um mehrere Sammlungen oder paginierte Antworten von Ressourcen zurückzugeben :use App\User; use App\Http\Resources\User as UserResource; Route::get('/user', function () { return UserResource::collection(User::all()); });
Natürlich können Sie mit der oben genannten Methode keine zusätzlichen Metadaten hinzufügen und diese mit der Sammlung zurückgeben. Wenn Sie eine benutzerdefinierte Ressourcensammlungsantwort benötigen, müssen Sie eine dedizierte Ressource erstellen, um die Sammlung darzustellen:
php artisan make:resource UserCollection
Sie können problemlos alle Metadaten definieren, die Sie in der Antwort in der generierten Ressourcensammlungsklasse zurückgeben möchten :
<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\ResourceCollection; class UserCollection extends ResourceCollection{ /** * 将资源集合转换成数组。 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return [ 'data' => $this->collection, 'links' => [ 'self' => 'link-value', ], ]; } }
Sie können eine definierte Ressourcensammlung in einer Route oder einem Controller zurückgeben:
use App\User; use App\Http\Resources\UserCollection; Route::get('/users', function () { return new UserCollection(User::all()); });
Schützen Sie den Schlüssel der Sammlung
Beim Zurückgeben einer Ressourcensammlung von einer Route, Laravel Setzt die Schlüssel der Sammlung zurück, sodass sie in einfacher numerischer Reihenfolge vorliegen. Allerdings kann das Attribut
preserveKeys
zur Ressourcenklasse hinzugefügt werden, um anzugeben, ob der Sammlungsschlüssel beibehalten werden soll:<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class User extends JsonResource{ /** * 指示是否应保留资源的集合键。 * * @var bool */ public $preserveKeys = true; }
Wenn das Attribut
preserveKeys
auftrue
gesetzt ist, wird der Sammlungsschlüssel geschützt :use App\User; use App\Http\Resources\User as UserResource; Route::get('/user', function () { return UserResource::collection(User::all()->keyBy->id); });
Angepasste Basisressourcenklasse
Normalerweise Ressourcensammlung
$this->collection
Die Eigenschaften werden automatisch ausgefüllt, was dazu führt, dass jedes Element der Sammlung seiner individuellen Ressourcenklasse zugeordnet wird. Es wird davon ausgegangen, dass eine einzelne Ressourcenklasse der Klassenname einer Sammlung ist, jedoch ohne die ZeichenfolgeCollection
am Ende.Zum Beispiel ordnet
UserCollection
die angegebene Benutzerinstanz der RessourceUser
zu. Um dieses Verhalten anzupassen, können Sie das Attribut$collects
der Ressourcensammlung überschreiben:<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\ResourceCollection; class UserCollection extends ResourceCollection{ /** * collects 属性定义了资源类。 * * @var string */ public $collects = 'App\Http\Resources\Member'; }
Ressource schreiben
{ Tipp } Falls Sie es noch nicht gelesen haben Konzeptübersicht, dann wird dringend empfohlen, dass Sie es lesen, bevor Sie mit der Lektüre dieses Dokuments fortfahren.
Im Wesentlichen ist die Rolle von Ressourcen einfach. Sie müssen lediglich ein bestimmtes Modell in ein Array konvertieren. Daher enthält jede Ressource eine
toArray
-Methode, die Ihre Modelleigenschaften in ein API-freundliches Array umwandelt, das an den Benutzer zurückgegeben werden kann:<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class User extends JsonResource{ /** * 将资源转换成数组。 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, ]; } }
Sie können definierte Ressourcen in Routen oder Controllern zurückgeben:
use App\User; use App\Http\Resources\User as UserResource; Route::get('/user', function () { return new UserResource(User::find(1)); });
Verknüpfungen
Wenn Sie verknüpfte Ressourcen in die Antwort einbeziehen möchten, müssen Sie sie nur zu
toArray
hinzufügen im von der Methode zurückgegebenen Array. Im folgenden Beispiel verwenden wir diePost
-Methode dercollection
-Ressource, um den Artikel des Benutzers zur Ressourcenantwort hinzuzufügen:/** * 将资源转换成数组。 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request){ return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'posts' => PostResource::collection($this->posts), 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, ]; }
{tip} Wenn Sie nur den Beitrag des Benutzers hinzufügen möchten die Ressourcenantwort, wenn die Assoziation geladen wurde. Zugehörige Ressourcen wurden nur hinzugefügt, siehe Dokument Bedingte Assoziation.
Ressourcensammlung
Ressourcen konvertieren ein einzelnes Modell in ein Array, während Ressourcensammlungen eine Sammlung mehrerer Modelle in ein Array umwandeln. Alle Ressourcen bieten eine
collection
-Methode zum Generieren einer „temporären“ Ressourcensammlung, sodass Sie nicht für jeden Modelltyp eine Ressourcensammlungsklasse schreiben müssen:use App\User; use App\Http\Resources\User as UserResource; Route::get('/user', function () { return UserResource::collection(User::all()); });
Wenn Sie jedoch die Metadaten der zurückgegebenen Sammlung anpassen müssen, müssen Sie diese noch definieren Definieren Sie eine Ressourcensammlung:
<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\ResourceCollection; class UserCollection extends ResourceCollection{ /** * 将资源集合转换成数组 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return [ 'data' => $this->collection, 'links' => [ 'self' => 'link-value', ], ]; } }
Genau wie eine einzelne Ressource können Sie eine Ressourcensammlung direkt in einer Route oder einem Controller zurückgeben:
use App\User; use App\Http\Resources\UserCollection; Route::get('/users', function () { return new UserCollection(User::all()); });
Datenumbruch
Wenn die Ressourcenantwort in JSON konvertiert wird, wird die Ressource der obersten Ebene standardmäßig in den
data
-Schlüssel eingeschlossen. Eine typische Antwort auf eine Ressourcensammlung sieht also so aus:{ "data": [ { "id": 1, "name": "Eladio Schroeder Sr.", "email": "therese28@example.com", }, { "id": 2, "name": "Liliana Mayert", "email": "evandervort@example.com", } ] }
Sie können das Umschließen von Ressourcen der obersten Ebene mit der Methode
withoutWrapping
der Ressourcenbasisklasse deaktivieren. Normalerweise sollten Sie diese Methode inAppServiceProvider
oder anderen Dienstanbietern aufrufen, die bei jeder Anforderung des Programms geladen werden:<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Http\Resources\Json\Resource; class AppServiceProvider extends ServiceProvider{ /** * 在注册后进行服务的启动 * * @return void */ public function boot() { Resource::withoutWrapping(); } /** * 在容器中注册绑定 * * @return void */ public function register() { // } }
{note} Die
withoutWrappin
-Methode deaktiviert nur die oberste Ebene Das Ressourcenpaket löscht nicht diedata
-Schlüssel, die Sie manuell zur Ressourcensammlung hinzugefügt haben.Verschachtelte Ressourcen umschließen
Sie haben völlige Freiheit bei der Entscheidung, wie Ressourcenzuordnungen umschlossen werden. Wenn Sie möchten, dass alle Ressourcensammlungen in
data
-Schlüssel eingeschlossen werden, unabhängig davon, wie verschachtelt sie sind, müssen Sie für jede Ressource eine Ressourcensammlungsklasse definieren und die zurückgegebene Sammlung indata
-Schlüssel einschließen.Natürlich können Sie befürchten, dass die Ressource der obersten Ebene in zwei
data
Schlüssel verpackt wird. Seien Sie versichert, Laravel lässt niemals zu, dass Ihre Ressourcen doppelt verpackt werden, sodass Sie sich keine Sorgen machen müssen, dass die konvertierte Sammlung von Ressourcen mehrfach verschachtelt ist:<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\ResourceCollection; class CommentsCollection extends ResourceCollection{ /** * 将资源集合转换成数组 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return ['data' => $this->collection]; } }
Datenumbruch und Paginierung
Wann Wenn Sie eine paginierte Sammlung in einer Ressourcenantwort zurückgeben, verpackt Laravel Ihre Ressourcendaten in
withoutWrapping
-Schlüssel, selbst wenn Sie diedata
-Methode aufrufen. Dies liegt daran, dass es in Paginierungsantworten immer die Schlüsselmeta
undlinks
gibt, die Informationen zum Paginierungsstatus enthalten:{ "data": [ { "id": 1, "name": "Eladio Schroeder Sr.", "email": "therese28@example.com", }, { "id": 2, "name": "Liliana Mayert", "email": "evandervort@example.com", } ], "links":{ "first": "http://example.com/pagination?page=1", "last": "http://example.com/pagination?page=1", "prev": null, "next": null }, "meta":{ "current_page": 1, "from": 1, "last_page": 1, "path": "http://example.com/pagination", "per_page": 15, "to": 10, "total": 10 } }
Paginierung
Sie Eine Paginierungsinstanz kann an
collection
der Ressource übergeben werden Methode oder benutzerdefinierte Ressourcensammlung:use App\User; use App\Http\Resources\UserCollection; Route::get('/users', function () { return new UserCollection(User::paginate()); });
Die paginierte Antwort enthält immer
meta
undlinks
Schlüssel enthalten Paging-Statusinformationen:{ "data": [ { "id": 1, "name": "Eladio Schroeder Sr.", "email": "therese28@example.com", }, { "id": 2, "name": "Liliana Mayert", "email": "evandervort@example.com", } ], "links":{ "first": "http://example.com/pagination?page=1", "last": "http://example.com/pagination?page=1", "prev": null, "next": null }, "meta":{ "current_page": 1, "from": 1, "last_page": 1, "path": "http://example.com/pagination", "per_page": 15, "to": 10, "total": 10 } }
Bedingte Attribute
Manchmal möchten Sie einer Ressource möglicherweise Attribute hinzufügen, wenn eine bestimmte Bedingung erfüllt ist als Antwort. Beispielsweise möchten Sie möglicherweise einen Wert zur Ressourcenantwort hinzufügen, wenn der aktuelle Benutzer ein „Administrator“ ist. In diesem Fall stellt Laravel einige Hilfsmethoden zur Verfügung, die Ihnen bei der Lösung des Problems helfen. Die
when
-Methode kann verwendet werden, um Attribute bedingt zur Ressourcenantwort hinzuzufügen:/** * 将资源转换成数组 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request){ return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'secret' => $this->when(Auth::user()->isAdmin(), 'secret-value'), 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, ]; }
Im obigen Beispiel landet der
isAdmin
-Schlüssel nur dann, wenn dietrue
-Methodesecret
Ressource zurückgibt wird in der Antwort zurückgegeben. Wenn diese Methodefalse
zurückgibt, wird der Schlüsselsecret
entfernt, bevor die Ressourcenantwort an den Client gesendet wird. Mit derwhen
-Methode können Sie die Verwendung von bedingten Anweisungen zum Verketten von Arrays vermeiden und stattdessen Ihre Ressourcen eleganter schreiben. Diewhen
-Methode akzeptiert auch einen Abschluss als zweiten Parameter, und der zurückgegebene Wert wird nur dann aus dem Abschluss berechnet, wenn die gegebene Bedingungtrue
ist:'secret' => $this->when(Auth::user()->isAdmin(), function () { return 'secret-value'; }),
Daten bedingt zusammenführen
Manchmal möchten Sie möglicherweise mehrere Attribute zur Ressourcenantwort hinzufügen, wenn eine bestimmte Bedingung erfüllt ist. In diesem Fall können Sie die Methode
mergeWhen
verwenden, um der Antwort mehrere Attribute hinzuzufügen, wenn die gegebene Bedingungtrue
ist:/** * 将资源转换成数组 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request){ return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, $this->mergeWhen(Auth::user()->isAdmin(), [ 'first-secret' => 'value', 'second-secret' => 'value', ]), 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, ]; }
Wenn die gegebene Bedingung
false
ist, sind diese Attribute ebenfalls vorhanden entfernt, bevor die Ressourcenantwort an den Client gesendet wird.{note} Die
mergeWhen
-Methode sollte nicht in Arrays verwendet werden, die Zeichenfolgen und numerische Tasten mischen. Darüber hinaus sollte es nicht in einem Array nicht aufeinanderfolgender numerischer Tasten verwendet werden.Bedingte Zuordnung
Zusätzlich zum bedingten Hinzufügen von Eigenschaften können Sie auch Attribute bedingt hinzufügen, basierend darauf, ob die Modellzuordnung erfolgt ist geladen. Fügen Sie die Zuordnung in Ihre Ressourcenantwort ein. Dadurch können Sie im Controller entscheiden, welche Modellzuordnungen geladen werden, sodass Ihre Ressourcen diese erst hinzufügen können, nachdem die Modellzuordnungen geladen wurden.
Auf diese Weise vermeiden Sie „N 1“-Abfrageprobleme in Ihren Ressourcen. Sie sollten die Methode
whenLoaded
verwenden, um Assoziationen bedingt zu laden. Um das Laden unnötiger Assoziationen zu vermeiden, akzeptiert diese Methode den Namen der Assoziation als Parameter anstelle der Assoziation selbst:/** * 将资源转换成数组 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request){ return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'posts' => PostResource::collection($this->whenLoaded('posts')), 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, ]; }
Wenn im obigen Beispiel die Assoziation nicht geladen ist, ist der Schlüssel
posts
vorhanden Die Ressource Die Antwort wird gelöscht, bevor sie an den Client gesendet wird.Bedingte Zwischentabelleninformationen
Zusätzlich zum bedingten Einschließen von Assoziationen in Ihre Ressourcenantwort können Sie mit der
whenPivotLoaded
-Methode auch bedingt eine Viele-zu-Viele-Assoziation aus einer Zwischentabelle extrahieren Daten hinzufügen.whenPivotLoaded
Der erste von der Methode akzeptierte Parameter ist der Name der Zwischentabelle. Der zweite Parameter ist ein Abschluss, der den zurückzugebenden Wert definiert, wenn die Zwischentabelleninformationen im Modell verfügbar sind:/** * 将资源转换成数组 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request){ return [ 'id' => $this->id, 'name' => $this->name, 'expires_at' => $this->whenPivotLoaded('role_user', function () { return $this->pivot->expires_at; }), ]; }
Wenn Ihre Zwischentabelle einen anderen Accessor als
pivot
verwendet, können Sie <🎜 verwenden > Methode:whenPivotLoadedAs
/** * 将资源转换成数组 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request){ return [ 'id' => $this->id, 'name' => $this->name, 'expires_at' => $this->whenPivotLoadedAs('subscription', 'role_user', function () { return $this->subscription->expires_at; }), ]; }
Metadaten hinzufügen Einige JSON-API-Standards erfordern das Hinzufügen von Metadaten in Ressourcen- und Ressourcensammlungsantworten. Dazu gehören normalerweisefür die Ressource oder verwandte Ressourcen oder einige Metadaten über die Ressource selbst. Wenn Sie zusätzliche Metadaten zur Ressource zurückgeben müssen, fügen Sie diese einfach in die Methode
links
ein. Wenn Sie beispielsweise eine Ressourcensammlung konvertieren, müssen Sie möglicherweisetoArray
-Informationen hinzufügen:links
/** * 将资源转换成数组 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request){ return [ 'data' => $this->collection, 'links' => [ 'self' => 'link-value', ], ]; }
Wenn Sie Ihren Ressourcen zusätzliche Metadaten hinzufügen, müssen Sie sich keine Sorgen über das Überschreiben dermachen, die Laravel automatisch hinzufügt, wenn Rückgabe einer paginierten Antwort 🎜> oder
links
Taste. Alle anderen von Ihnen hinzugefügtenmeta
werden mit den in der paginierten Antwort hinzugefügtenlinks
zusammengeführt.links
Metadaten der obersten Ebene
Manchmal möchten Sie möglicherweise einige Metadaten zur Ressourcenantwort hinzufügen, wenn die Ressource als Ressource der obersten Ebene zurückgegeben wird. Dazu gehören in der Regel Metainformationen über die gesamte Antwort. Sie können
with
-Methoden in Ressourcenklassen hinzufügen, um Metadaten zu definieren. Diese Methode sollte ein Array von Metadaten zurückgeben, die in die Ressourcenantwort aufgenommen werden, wenn die Ressource als Ressource der obersten Ebene gerendert wird:<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\ResourceCollection; class UserCollection extends ResourceCollection{ /** * 将资源集合转换成数组 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return parent::toArray($request); } /** * 返回应该和资源一起返回的其他数据数组 * * @param \Illuminate\Http\Request $request * @return array */ public function with($request) { return [ 'meta' => [ 'key' => 'value', ], ]; } }
Metadaten beim Erstellen der Ressource hinzufügen
Sie sind auch Top Beim Erstellen von Ressourceninstanzen in Routen oder Controllern können Daten auf -Ebene hinzugefügt werden. Alle Ressourcen können die Methode
additional
verwenden, um eine Reihe von Daten zu akzeptieren, die der Ressourcenantwort hinzugefügt werden sollen:return (new UserCollection(User::all()->load('roles'))) ->additional(['meta' => [ 'key' => 'value', ] ]);
Antwortressource
wie du weißt, Ressourcen können direkt in Routen und Controllern zurückgegeben werden:
use App\User; use App\Http\Resources\User as UserResource; Route::get('/user', function () { return new UserResource(User::find(1)); });
Aber manchmal müssen Sie möglicherweise die HTTP-Antwort anpassen, bevor Sie sie an den Client senden. Sie haben zwei Möglichkeiten. Zunächst können Sie die Methode
response
in einer Kette aufrufen. Diese Methode gibt eineIlluminateHttpResponse
-Instanz zurück, sodass Sie die Antwortheaderinformationen anpassen können:use App\User; use App\Http\Resources\User as UserResource; Route::get('/user', function () { return (new UserResource(User::find(1))) ->response() ->header('X-Value', 'True'); });
Darüber hinaus können Sie auch eine
withResponse
-Methode in der Ressource definieren. Diese Methode wird aufgerufen, wenn die Ressource als Ressource der obersten Ebene als Antwort verwendet wird:<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class User extends JsonResource{ /** * 资源转换成数组 * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return [ 'id' => $this->id, ]; } /** * 自定义响应 * * @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Response $response * @return void */ public function withResponse($request, $response) { $response->header('X-Value', 'True'); } }
Dieser Artikel wurde zuerst auf der Website LearnKu.com veröffentlicht.
- Schutz Sammlungsschlüssel