English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Heutzutage ist die Hauptarbeit der Programmierer auf dem Server nicht mehr das Anpassen von Mustern, sondern die Erstellung von API-Schnittstellen, die auf JSON basieren. Leider ist der Stil der Schnittstellen, die von den meisten Leuten erstellt werden, oft unterschiedlich, was viele unnötige Kommunikationskosten bei der Integration der Systeme mit sich bringt. Wenn du ähnliche Probleme hast, dann不妨关注一下 JSONAPI ,es ist ein Standard für die Erstellung von API-Schnittstellen, der auf JSON basiert. Ein einfaches API-Schnittstellenbeispiel könnte wie folgt aussehen:
JSONAPI
Kurzinfo: Der data-Bereich im Wurzelknoten wird verwendet, um den Inhalt des Hauptobjekts zu platzieren. Die Felder type und id sind obligatorisch und dienen dazu, den Typ und die Identifikation des Hauptobjekts anzuzeigen. Andere einfache Attribute werden in der Rubrik attributes platziert. Wenn das Hauptobjekt ein- zu-eins- oder mehr-zu-eins-Beziehungen zu anderen Objekten hat, werden diese in der Rubrik relationships platziert. Es wird jedoch nur eine Verbindung über die Felder type und id hergestellt, und der tatsächliche Inhalt der verknüpften Objekte wird in der Rubrik included im Wurzelknoten platziert.
Mit JSONAPI wird der Prozess der Datenanalyse standardisiert und spart unnötige Kommunikationskosten. Wenn man jedoch JSONAPI-Daten manuell erstellen muss, ist das recht umständlich. Zum Glück lässt sich der Implementierungsprozess durch die Verwendung von Fractal relativ automatisieren. Der obige Beispiel könnte mit Fractal so aussehen:
<?php use League\Fractal\Manager; use League\Fractal\Resource\Collection; $articles = [ [ 'id' => 1, 'title' => 'JSON API paints my bikeshed!', 'body' => 'The shortest article. Ever.', 'author' => [ 'id' => 42, 'name' => 'John', ], ], ]; $manager = new Manager(); $resource = new Collection($articles, new ArticleTransformer()); $manager->parseIncludes('author'); $manager->createData($resource)->toArray(); ?>
Wenn ich die Lieblings-PHP-Toolbox wählen müsste, wäre Fractal sicherlich auf der Liste, da er die Implementierungsdetails versteckt und es dem Benutzer ermöglicht, ohne das JSONAPI-Protokoll verstehen zu müssen, sofort loszulegen. Wenn Sie jedoch Fractal in Ihrem eigenen Projekt verwenden möchten, können Sie im Vergleich zur direkten Verwendung von Fractal Fractalistic ausprobieren, der Fractal verpackt und ihn nutzbarer macht:
<?php Fractal::create() ->collection($articles) ->transformWith(new ArticleTransformer()) ->includeAuthor() ->toArray(); ?>
Wenn Sie PHP ohne Framework schreiben, dann ist Fractalistic die beste Wahl, aber wenn Sie einen Full-Stack-Framework verwenden, dann ist Fractalistic möglicherweise nicht elegant genug, da er sich nicht perfekt mit den bereits vorhandenen Funktionen des Frameworks integrieren kann. Nehmen wir Lavaral als Beispiel, das selbst eine API Resources-Funktion integriert hat. Auf dieser Basis habe ich einen JsonApiSerializer implementiert, der sich perfekt in das Framework integriert, und der Code sieht so aus:
<?php namespace App\Http\Serializers; use Illuminate\Http\Resources\MissingValue; use Illuminate\Http\Resources\Json\Resource; use Illuminate\Http\Resources\Json\ResourceCollection; use Illuminate\Pagination\AbstractPaginator; class JsonApiSerializer implements \JsonSerializable { protected $resource; protected $resourceValue; protected $data = []; protected static $included = []; public function __construct($resource, $resourceValue) { $this->resource = $resource; $this->resourceValue = $resourceValue; } public function jsonSerialize() { foreach ($this->resourceValue as $key => $value) { if ($value instanceof Resource) { $this->serializeResource($key, $value); } else { $this->serializeNonResource($key, $value); } } if (!$this->isRootResource()) { return $this->data; } $result = [ 'data' => $this->data, ]; if (static::$included) { $result['included'] = static::$included; } if (!$this->resource->resource instanceof AbstractPaginator) { return $result; } $paginated = $this;->resource->resource->toArray(); $result['links'] = $this;->links($paginated); $result['meta'] = $this;->meta($paginated); return $result; } geschützte Funktion serializeResource($key, $value, $type = null) { if ($type === null) { $type = $key; } if ($value->resource instanceof MissingValue) { return; } if ($value instanceof ResourceCollection) { foreach ($value as $k => $v) { $this->serializeResource($k, $v, $type); } } elseif (is_string($type)) { $included = $value->resolve(); $data = [ 'type' => $included['type'], 'id' => $included['id'], ]; if (is_int($key)) { $this->data['relationships'][$type]['data'][] = $data; } else { $this->data['relationships'][$type]['data'] = $data; } static::$included[] = $included; } else { $this->data[] = $value->resolve(); } } geschützte Funktion serializeNonResource($key, $value) { switch ($key) { case 'id': $value = (string)$value; case 'type': case 'links': $this->data[$key] = $value; break; standard: $this->data['attributes'][$key] = $value; } } geschützte Funktion links($paginated) { return [ 'first' => $paginated['first_page_url'] ?? null, 'last' => $paginated['last_page_url'] ?? null, 'prev' => $paginated['prev_page_url'] ?? null, 'next' => $paginated['next_page_url'] ?? null, ]; } protected function meta($paginated) { return [ 'current_page' => $paginated['current_page'] ?? null, 'from' => $paginated['from'] ?? null, 'last_page' => $paginated['last_page'] ?? null, 'per_page' => $paginated['per_page'] ?? null, 'to' => $paginated['to'] ?? null, 'total' => $paginated['total'] ?? null, ]; } protected function isRootResource() { return isset($this->resource->isRoot) && $this->resource->isRoot; } } ?>
Der entsprechende Resource ist im Wesentlichen gleich geblieben, nur wurde der Rückgabewert geändert:
<?php namespace App\Http\Resources; use App\Article; use Illuminate\Http\Resources\Json\Resource; use App\Http\Serializers\JsonApiSerializer; class ArticleResource extends Resource { public function toArray($request) { $value = [ 'type' => 'articles', 'id' => $this->id, 'name' => $this->name, 'author' => $this->whenLoaded('author'), ]; return new JsonApiSerializer($this, $value); } } ?>
Der entsprechende Controller ist ähnlich wie zuvor, nur wurde eine Eigenschaft isRoot hinzugefügt, um den Root zu identifizieren:
<?php namespace App\Http\Controllers; use App\Article; use App\Http\Resources\ArticleResource; class ArticleController extends Controller { protected $article; public function __construct(Article $article) { $this->article = $article; } public function show($id) { $article = $this->article->with('author')->findOrFail($id); $resource = new ArticleResource($article); $resource->isRoot = true; return $resource; } } ?>
Der Prozess hat die Architektur von Laravel nicht zu stark verändert und ist derzeit die beste Lösung für die Implementierung von JSONAPI in Laravel. Wer interessiert ist, kann die Implementierung von JsonApiSerializer untersuchen, obwohl es nur einhundertundzwanzig Zeilen Code gibt, habe ich sehr viel Mühe in die Implementierung gesteckt, jede Zeile war mühsam.
Zusammenfassung
Die oben genannten sind die Anwendungsfälle von JSONAPI in PHP, die von mir vorgestellt wurden. Ich hoffe, sie sind Ihnen hilfreich. Wenn Sie Fragen haben, lassen Sie mir bitte eine Nachricht da, ich werde mich so schnell wie möglich bei Ihnen melden!
Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet entnommen und gehört dem Urheberrechtsinhaber. Der Inhalt wurde von Internetnutzern freiwillig eingereicht und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine rechtlichen Verantwortlichkeiten. Wenn Sie verdächtige urheberrechtliche Inhalte entdecken, freuen wir uns über eine E-Mail an: notice#oldtoolbag.com (Bitte ersetzen Sie # durch @, wenn Sie eine Beschwerde einreichen, und fügen Sie relevante Beweise bei. Sobald die Inhalte überprüft sind, wird diese Website die beanstandeten Inhalte sofort löschen.)