現在、サーバー プログラマーの主な仕事は、テンプレートを設定することではなく、JSON ベースの API インターフェイスを作成することです。残念ながら、インターフェイスの記述スタイルは人によって大きく異なることが多く、これによりシステム統合に多くの不必要な通信コストが発生します。同じような問題がある場合は、JSON に基づいて API を構築するための標準である JSONAPI に注目することをお勧めします。簡単な API インターフェイスは大まかに次のとおりです:
JSONAPI
簡単な説明: ルート ノードのデータは、メイン オブジェクトのコンテンツを配置するために使用されます。type と id は、オブジェクトのタイプと識別を表す必須フィールドです。メイン オブジェクト、他のすべての単純な属性は属性に配置されます。メイン オブジェクトに 1 対 1、1 対多、およびその他の関連オブジェクトがある場合、それらはリレーションシップに配置されます。 type フィールドと id フィールド、および関連するオブジェクトの実際のコンテンツがルート ノードに含まれます。
JSONAPI を使用すると、データ解析のプロセスが標準化され、不必要な通信コストが節約されます。ただし、JSONAPI データを手動で構築するのは依然として非常に面倒です。幸いなことに、Fractal を使用すると、実装プロセスは比較的自動化できます。おそらく、次のようになります。お気に入りの PHP ツールキットを選択するように求められたら、Fractal がリストにあるはずです。これにより、実装の詳細が隠蔽され、ユーザーは JSONAPI プロトコルをまったく知らなくても始めることができます。ただし、Fractal を直接使用する代わりに、独自のプロジェクトで使用したい場合は、使いやすくするために Fractal をカプセル化する Fractalistic を試すことができます:
<?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(); ?>
PHP を裸で書いている場合、Fractalistic は基本的に最良の選択ですが、フルスタック フレームワークを使用する場合、Fractalistic はフレームワーク自体の既存の機能とより完全に統合できないため、十分にエレガントではない可能性があります。例として Lavaral 自体には、組み込みの機能があります。これに基づいて、フレームワークと完全に統合できる JsonApiSerializer を実装しました。コードは次のとおりです。変更されました:
<?php Fractal::create() ->collection($articles) ->transformWith(new ArticleTransformer()) ->includeAuthor() ->toArray(); ?>
の対応するコントローラーは、ルートを識別するために isRoot 属性が追加されている点を除いて、オリジナルと似ています:
<?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; } protected function 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(); } } protected function serializeNonResource($key, $value) { switch ($key) { case 'id': $value = (string)$value; case 'type': case 'links': $this->data[$key] = $value; break; default: $this->data['attributes'][$key] = $value; } } protected function 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; } } ?>
プロセス全体は、Laravel のアーキテクチャにあまり侵入しません。 Laravel は現在 JSONAPI を実装していると言えます。興味があれば、JsonApiSerializer の実装を検討してください。ただし、実装には多大な労力を費やしました。どの段階も大変な作業だと言われます。
関連する推奨事項:
Ajax と jsonp の使用法の概要
json 形式の配列を Excel テーブルにダウンロードする JavaScript の詳細な例
以上がPHP での JSONAPI のアプリケーションの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。