您好,欢迎访问一九零五行业门户网

JSONAPI在PHP中的使用方法

这次给大家带来jsonapi在php中的使用方法,jsonapi在php中使用的注意事项有哪些,下面就是实战案例,一起来看一下。
现在服务端程序员的主要工作已经不再是套模版,而是编写基于 json 的 api 接口。可惜大家编写接口的风格往往迥异,这就给系统集成带来了很多不必要的沟通成本,如果你有类似的困扰,那么不妨关注一下 jsonapi ,它是一个基于 json 构建 api 的规范标准,一个简单的 api 接口大致如下所示:
jsonapi
简单说明一下:根节点中的 data 用来放置主对象的内容,其中 type 和 id 是必须要有的字段,用来表示主对象的类型和标识,其它简单的属性统统放置到 attributes 里,如果主对象存在一对一、一对多等关联对象,那么放置到 relationships 里,不过只是通过 type 和 id 字段放置一个链接,关联对象的实际内容统统放置在根接点中的 included 里。
有了 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 的话,那么 fractalistic 基本就是最佳选择了,不过如果你使用了一些全栈框架的话,那么 fractalistic 可能还不够优雅,因为它无法和框架本身已有的功能更完美的融合,以 lavaral 为例,它本身内置了一个 api resources 功能,在此基础上我实现了一个 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);   } } ?>
对应的 controller 也和原来差不多,只是加入了一个 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 的架构进行太大的侵入,可以说是目前 laravel 实现 jsonapi 的最优解决方案了,有兴趣的可以研究一下 jsonapiserializer 的实现,虽然只有一百多行代码,但是我却费了好大的力气才实现,可以说是行行皆辛苦啊。
相信看了本文案例你已经掌握了方法,更多精彩请关注其它相关文章!
推荐阅读:
怎么提速优化vue-cli的代码
vue.js通用应用框架nuxt.js使用详解
js实现标签滚动切换
以上就是jsonapi在php中的使用方法的详细内容。
其它类似信息

推荐信息