English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Ahora, el trabajo principal del programador del lado del servidor ya no es usar plantillas, sino escribir interfaces de API basadas en JSON. Desafortunadamente, el estilo de escritura de las interfaces de muchos es muy diferente, lo que lleva a muchos costos de comunicación innecesarios en la integración del sistema. Si tienes problemas similares, es mejor prestar atención a JSONAPI, que es un estándar de norma para construir API basadas en JSON. Un interfaz de API simple se muestra a continuación:
JSONAPI
Se explica de manera sencilla: el campo data en el nodo raíz se utiliza para放置主对象的内容,entre los que type y id son campos obligatorios, utilizados para representar el tipo y la identificación del objeto principal. Otros atributos simples se colocan en attributes. Si el objeto principal tiene objetos asociados uno a uno, uno a muchos, etc., se colocan en relationships. Sin embargo, solo se coloca un enlace a través de los campos type e id, y el contenido real de los objetos asociados se coloca en included en el nodo raíz.
Con JSONAPI, el proceso de análisis de datos se ha vuelto más estándar, ahorrando costos de comunicación innecesarios. Sin embargo, construir manualmente datos JSONAPI puede ser muy complicado, afortunadamente, usar Fractal puede hacer que el proceso de implementación sea más automatizado, el ejemplo anterior si se realiza con Fractal sería algo así:
<?php use League\Fractal\Manager; use League\Fractal\Resource\Collection; $articles = [ [ 'id' => 1, 'title' => 'JSON API pinta mi cochera!', 'body' => 'El artículo más corto. Jamás.', 'author' => [ 'id' => 42, 'name' => 'John', ], ], ]; $manager = new Manager(); $resource = new Collection($articles, new ArticleTransformer()); $manager->parseIncludes('author'); $manager->createData($resource)->toArray(); ?>
Si me preguntan por mi paquete de herramientas favorito de PHP, Fractal sin duda estaría en la lista, ya que oculta los detalles de la implementación, permitiendo que los usuarios comiencen a usarlo sin necesidad de entender el protocolo JSONAPI. Sin embargo, si quieres usarlo en tu propio proyecto, en lugar de usar Fractal directamente, puedes probar Fractalistic, que lo encapsula para que sea más útil:
<?php Fractal::create() ->collection($articles) ->transformWith(new ArticleTransformer()) ->includeAuthor() ->toArray(); ?>
Si escribes PHP sin trajes, Fractalistic es básicamente la mejor opción, pero si usas algún framework full-stack, Fractalistic puede que no sea lo suficientemente elegante, ya que no puede integrarse perfectamente con las funciones ya existentes del framework en sí. Por ejemplo, Laravel tiene una función de recursos de API integrada, y sobre esa base implementé un JsonApiSerializer que se integra perfectamente con el framework, el código es el siguiente:
<?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; } } ?>
El Resource es básicamente igual al anterior, pero se ha cambiado el valor de retorno:
<?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); } } ?>
El Controller correspondiente también es más o menos igual al original, pero se ha añadido una propiedad isRoot para identificar la raíz:
<?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; } } ?>
El proceso no ha invadido demasiado la arquitectura de Laravel, puede decirse que es la mejor solución actual para la implementación de JSONAPI en Laravel. Aquellos interesados pueden investigar la implementación de JsonApiSerializer, aunque solo tiene más de cien líneas de código, me costó mucho trabajo implementarlo, realmente es un trabajo arduo línea por línea.
Resumen
Lo mencionado anteriormente es lo que el editor les ha presentado sobre la aplicación de JSONAPI en PHP, esperamos que les sea útil. Si tienen alguna pregunta, no dudes en dejarme un mensaje, el editor responderá a tiempo.
Declaración: El contenido de este artículo se ha obtenido de la red, es propiedad del autor original, el contenido se ha contribuido y subido por los usuarios de Internet de manera autónoma. Este sitio no posee los derechos de propiedad, no ha sido editado por humanos y no asume ninguna responsabilidad legal relacionada. Si encuentra contenido sospechoso de infracción de derechos de autor, le invitamos a enviar un correo electrónico a: notice#oldtoolbag.com (al enviar un correo electrónico, por favor reemplace # con @) para denunciar y proporcionar evidencia relevante. Una vez confirmado, este sitio eliminará inmediatamente el contenido sospechoso de infracción.