Maison  >  Article  >  interface Web  >  Application de JSONAPI en PHP

Application de JSONAPI en PHP

小云云
小云云original
2017-12-25 14:54:561446parcourir

Désormais, la tâche principale des programmeurs côté serveur n'est plus de définir des modèles, mais d'écrire des interfaces API basées sur JSON. Malheureusement, tout le monde a souvent des styles d'écriture d'interfaces très différents, ce qui entraîne de nombreux coûts de communication inutiles pour l'intégration du système. Si vous rencontrez des problèmes similaires, vous pourriez aussi bien faire attention à JSONAPI, qui est un standard pour créer des API basées sur JSON. un simple L'interface API de Pour représenter le type et l'identité de l'objet principal, d'autres attributs simples sont placés dans les attributs. Si l'objet principal a un à un, un à plusieurs et d'autres objets associés, alors ils sont placés. dans les relations, mais seul un lien est placé via les champs type et id, le contenu réel des objets associés est tous placé dans le contact racine.

Avec JSONAPI, le processus d'analyse des données devient standardisé, ce qui permet d'économiser des coûts de communication inutiles. Cependant, il est toujours très difficile de construire manuellement des données JSONAPI. Heureusement, en utilisant Fractal, le processus d'implémentation peut être relativement automatisé. Si l'exemple ci-dessus est implémenté à l'aide de Fractal, il ressemblera probablement à ceci :

<.>

Si on me demandait de choisir ma boîte à outils PHP préférée, Fractal serait certainement sur la liste. Il masque les détails d'implémentation et permet aux utilisateurs de démarrer sans avoir à comprendre le protocole JSONAPI. . Mais si vous souhaitez l'utiliser dans votre propre projet, au lieu d'utiliser Fractal directement, vous pouvez essayer Fractalistic, qui encapsule Fractal pour le rendre plus facile à utiliser :


<?php
use League\Fractal\Manager;
use League\Fractal\Resource\Collection;
$articles = [
  [
    &#39;id&#39; => 1,
    &#39;title&#39; => &#39;JSON API paints my bikeshed!&#39;,
    &#39;body&#39; => &#39;The shortest article. Ever.&#39;,
    &#39;author&#39; => [
      &#39;id&#39; => 42,
      &#39;name&#39; => &#39;John&#39;,
    ],
  ],
];
$manager = new Manager();
$resource = new Collection($articles, new ArticleTransformer());
$manager->parseIncludes(&#39;author&#39;);
$manager->createData($resource)->toArray();
?>

Si vous écrivez du PHP nu, alors Fractalistic est fondamentalement le meilleur choix. Cependant, si vous utilisez des frameworks full-stack, alors Fractalistic peut ne pas être assez élégant car il ne peut pas s'intégrer aux fonctions existantes du framework lui-même. intégration parfaite, prenons Lavalal comme exemple. Il dispose d'une fonction API Resources intégrée. Sur cette base, j'ai implémenté un JsonApiSerializer qui peut être parfaitement intégré au framework :


La Ressource correspondant à
<?php
Fractal::create()
  ->collection($articles)
  ->transformWith(new ArticleTransformer())
  ->includeAuthor()
  ->toArray();
?>

est fondamentalement la même que précédemment, sauf que la valeur de retour a été modifiée :


<?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 = [
      &#39;data&#39; => $this->data,
    ];
    if (static::$included) {
      $result[&#39;included&#39;] = static::$included;
    }
    if (!$this->resource->resource instanceof AbstractPaginator) {
      return $result;
    }
    $paginated = $this->resource->resource->toArray();
    $result[&#39;links&#39;] = $this->links($paginated);
    $result[&#39;meta&#39;] = $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 = [
        &#39;type&#39; => $included[&#39;type&#39;],
        &#39;id&#39; => $included[&#39;id&#39;],
      ];
      if (is_int($key)) {
        $this->data[&#39;relationships&#39;][$type][&#39;data&#39;][] = $data;
      } else {
        $this->data[&#39;relationships&#39;][$type][&#39;data&#39;] = $data;
      }
      static::$included[] = $included;
    } else {
      $this->data[] = $value->resolve();
    }
  }
  protected function serializeNonResource($key, $value)
  {
    switch ($key) {
      case &#39;id&#39;:
        $value = (string)$value;
      case &#39;type&#39;:
      case &#39;links&#39;:
        $this->data[$key] = $value;
        break;
      default:
        $this->data[&#39;attributes&#39;][$key] = $value;
    }
  }
  protected function links($paginated)
  {
    return [
      &#39;first&#39; => $paginated[&#39;first_page_url&#39;] ?? null,
      &#39;last&#39; => $paginated[&#39;last_page_url&#39;] ?? null,
      &#39;prev&#39; => $paginated[&#39;prev_page_url&#39;] ?? null,
      &#39;next&#39; => $paginated[&#39;next_page_url&#39;] ?? null,
    ];
  }
  protected function meta($paginated)
  {
    return [
      &#39;current_page&#39; => $paginated[&#39;current_page&#39;] ?? null,
      &#39;from&#39; => $paginated[&#39;from&#39;] ?? null,
      &#39;last_page&#39; => $paginated[&#39;last_page&#39;] ?? null,
      &#39;per_page&#39; => $paginated[&#39;per_page&#39;] ?? null,
      &#39;to&#39; => $paginated[&#39;to&#39;] ?? null,
      &#39;total&#39; => $paginated[&#39;total&#39;] ?? null,
    ];
  }
  protected function isRootResource()
  {
    return isset($this->resource->isRoot) && $this->resource->isRoot;
  }
}
?>

La Ressource correspondante Le contrôleur est également similaire à l'original, vient d'être ajouté. Un attribut isRoot est ajouté pour identifier la racine :


<?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 = [
      &#39;type&#39; => &#39;articles&#39;,
      &#39;id&#39; => $this->id,
      &#39;name&#39; => $this->name,
      &#39;author&#39; => $this->whenLoaded(&#39;author&#39;),
    ];
    return new JsonApiSerializer($this, $value);
  }
}
?>

L'ensemble du processus n'empiète pas trop sur l'architecture de Laravel. On peut dire que c'est actuellement la meilleure façon d'implémenter JSONAPI dans Laravel. Si vous êtes intéressé, vous pouvez étudier l'implémentation de JsonApiSerializer. Bien qu'il n'y ait que plus d'une centaine de lignes de code. a consacré beaucoup d'efforts à sa mise en œuvre. On peut dire que c'est un travail difficile.


Recommandations associées :

<?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(&#39;author&#39;)->findOrFail($id);
    $resource = new ArticleResource($article);
    $resource->isRoot = true;
    return $resource;
  }
}
?>


Résumé de la façon d'utiliser Ajax et jsonp


Explication détaillée de l'instance javascript à télécharger tableau au format json Plusieurs situations de transmission de valeur JSON et de réception PHP pour table Excel

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn