日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

php中使用json做api,JSONAPI在PHP中的应用

發布時間:2025/4/5 php 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php中使用json做api,JSONAPI在PHP中的应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

現在服務端程序員的主要工作已經不再是套模版,而是編寫基于 JSON 的 API 接口??上Т蠹揖帉懡涌诘娘L格往往迥異,這就給系統集成帶來了很多不必要的溝通成本,如果你有類似的困擾,那么不妨關注一下 JSONAPI ,它是一個基于 JSON 構建 API 的規范標準,一個簡單的 API 接口大致如下所示:

JSONAPI

簡單說明一下:根節點中的 data 用來放置主對象的內容,其中 type 和 id 是必須要有的字段,用來表示主對象的類型和標識,其它簡單的屬性統統放置到 attributes 里,如果主對象存在一對一、一對多等關聯對象,那么放置到 relationships 里,不過只是通過 type 和 id 字段放置一個鏈接,關聯對象的實際內容統統放置在根接點中的 included 里。

有了 JSONAPI,數據解析的過程變得規范起來,節省了不必要的溝通成本。不過如果要手動構建 JSONAPI 數據還是很麻煩的,好在通過使用 Fractal 可以讓實現過程相對自動化一些,上面的例子如果用 Fractal 實現大概是這個樣子:

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 進行了封裝,使其更好用:

Fractal::create()

->collection($articles)

->transformWith(new ArticleTransformer())

->includeAuthor()

->toArray();

?>

如果你是裸寫 PHP 的話,那么 Fractalistic 基本就是最佳選擇了,不過如果你使用了一些全棧框架的話,那么 Fractalistic 可能還不夠優雅,因為它無法和框架本身已有的功能更完美的融合,以 Lavaral 為例,它本身內置了一個 API Resources 功能,在此基礎上我實現了一個 JsonApiSerializer,可以和框架完美融合,代碼如下:

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 基本還和以前一樣,只是返回值改了一下:

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 屬性,用來識別根:

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 的實現,雖然只有一百多行代碼,但是我卻費了好大的力氣才實現,可以說是行行皆辛苦啊。

相關推薦:

總結

以上是生活随笔為你收集整理的php中使用json做api,JSONAPI在PHP中的应用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。