이 기사에서는 주로 PHP에서 JSONAPI를 적용하는 방법에 대한 심층 분석을 소개합니다. 필요한 친구가 참고할 수 있습니다.
이제 서버 프로그래머의 주요 임무는 더 이상 템플릿을 설정하는 것이 아니라 JSON 기반 API 인터페이스를 작성하는 것입니다. . 불행하게도 모든 사람은 매우 다른 스타일의 인터페이스를 가지고 있어 시스템 통합에 불필요한 통신 비용이 많이 발생합니다. 비슷한 문제가 있는 경우 JSON 기반 API 구축을 위한 표준인 JSONAPI에 주의를 기울이는 것이 좋습니다. 간단한 API 인터페이스는 대략 다음과 같습니다:
JSONAPI
간단한 설명: 루트 노드의 데이터는 기본 개체의 콘텐츠를 배치하는 데 사용됩니다. 여기서 유형과 ID는 필수 필드이며 유형과 기본 개체의 식별, 기타 모든 단순 속성은 기본 개체에 일대일, 일대다 및 기타 관련 개체가 있는 경우 관계에 배치됩니다. type 및 id 필드를 통해 관련 객체의 실제 콘텐츠가 루트 노드에 포함됩니다.
JSONAPI를 사용하면 데이터 구문 분석 프로세스가 표준화되어 불필요한 통신 비용이 절약됩니다. 그러나 JSONAPI 데이터를 수동으로 구성하는 것은 여전히 매우 번거로운 일입니다. 다행히 Fractal을 사용하면 구현 프로세스가 상대적으로 자동화될 수 있습니다. 위의 예를 Fractal로 구현하면 아마도 다음과 같을 것입니다.
<?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 툴킷을 선택하려면 Fractal이 목록에 있어야 하며, 구현 세부 정보를 숨겨 사용자가 JSONAPI 프로토콜을 전혀 몰라도 시작할 수 있도록 합니다. 하지만 자신의 프로젝트에서 Fractal을 직접 사용하는 대신 Fractalistic을 사용해 볼 수 있습니다. Fractal을 캡슐화하여 사용하기 더 쉽게 만듭니다.
<?php Fractal::create() ->collection($articles) ->transformWith(new ArticleTransformer()) ->includeAuthor() ->toArray(); ?>
PHP를 Naked로 작성하는 경우 Fractalistic이 기본적으로 가장 좋습니다. 그러나 일부 풀 스택 프레임워크를 사용하는 경우 Fractalistic은 프레임워크 자체의 기존 기능과 더 완벽하게 통합될 수 없기 때문에 충분히 우아하지 않을 수 있습니다. Lavaral을 예로 들면 API 리소스 기능이 내장되어 있습니다. , 이를 기반으로 프레임워크와 완벽하게 통합될 수 있는 JsonApiSerializer를 구현했습니다. 코드는 다음과 같습니다.
<?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; } } ?>
의 해당 Resource는 반환 값이 변경된 것을 제외하면 기본적으로 이전과 동일합니다.
<?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); } } ?>
의 컨트롤러도 이전과 동일하지만 루트를 식별하기 위해 isRoot 속성이 추가된다는 점만 제외하면
<?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; } } ?>
전체 프로세스가 Laravel의 아키텍처에 너무 많이 개입하지 않을 수 있습니다. 현재 JSONAPI를 구현하는 데 있어 Laravel이 가장 적합한 솔루션이라고 할 수 있습니다. JsonApiSerializer의 구현을 살펴보겠습니다. 코드는 100줄이 넘지만 많은 시간을 투자했습니다. 그것을 구현하기 위한 노력은 모든 단계가 힘든 작업이라고 할 수 있습니다.
위 내용은 모두를 위해 제가 정리한 내용입니다. 앞으로 모든 사람에게 도움이 되기를 바랍니다.
관련 글:
vue + less를 사용해 간단한 스킨 변경 기능을 구현하는 방법
Angular, React, Vue를 사용해 동일한 면접 질문 컴포넌트를 구현하는 방법
활용 jQuery는 하단으로 스크롤할 때 자동 로딩을 구현합니다.
Angular2.0에서 모달 대화 상자를 구현하는 방법
JS에서 모션 버퍼링 효과를 구현하는 방법(자세한 튜토리얼)
위 내용은 PHP에서 JSONAPI를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!