ride/lib-http-jsonapi

Ride框架的JSON API库

1.2.0 2024-06-26 08:52 UTC

This package is auto-updated.

Last update: 2024-08-26 09:06:54 UTC


README

PHP Ride框架的JSON API库。

请访问https://jsonapi.fullstack.org.cn 获取标准的完整参考。

本库包含哪些内容?

JsonApi

JsonApi 类是您实现的开端。它是资源适配器的容器,也是库中其他实例的工厂。您应该在执行任何其他API操作之前注册您的资源适配器。

JsonApiResourceAdapter

本库中唯一的接口是 JsonApiResourceAdapter 接口。该接口的实现将数据模型中的数据条目转换为JSON API资源。您需要为每个要通过API公开的数据类型提供一个此接口的实例。

JsonApiResource

JsonApiResource 类是资源的数据容器,例如来自您的数据模型的数据条目。该类的实例设置为API请求的响应文档,可以是单个实例,也可以是资源集合的数组。

JsonApiDocument

JsonApiDocument 是API请求响应文档的容器。您可以将资源或错误内容设置到该文档中。文档的内容甚至可以是严格意义上的元数据。

JsonApiDocument 实例持有您的 JsonApi 实例和一个 JsonApiQuery 实例。在将条目转换为资源时,它会被传递给资源适配器。使用 JsonApi 实例和 JsonApiQueryJsonApiResourceAdapter 可以根据客户端请求创建 JsonApiResource 实例。

JsonApiQuery

从您的传入查询参数中创建一个 JsonApiQuery 实例。该 JsonApiQuery 实例将为您提供对请求资源、分页、排序和筛选值的便捷访问。

代码示例

处理传入请求

您的API控制器可能如下所示

<?php

include ride\library\http\jsonapi\JsonApiQuery;
include ride\library\http\jsonapi\JsonApi;

/**
 * Controller for the blog post API
 */
class BlogPostController {
    
    /**
     * Constructs a new controller
     * @param ride\library\http\jsonapi\JsonApi $api
     */
    public function __construct(JsonApi $api) {
        $this->api = $api;
    }
    
    /**
     * Action to fetch a collection of blog posts
     */
    public function indexAction() {
        $query = $this->api->createQuery($_GET);
        $document = $this->api->createDocument($query);
        
        $blogPosts = $this->getBlogPosts($query, $total);
        
        $document->setResourceCollection(BlogPostResourceAdapter::TYPE, $blogPosts);
        $document->setMeta('total', $total);
        
        http_status_code($document->getStatusCode());
        if ($document->hasContent()) {
            header('Content-Type: ' . JsonApi::CONTENT_TYPE);
    
            echo json_encode($document);
        }
    }
    
    /**
     * Gets the blog posts from the data source
     * @param ride\library\http\jsonapi\JsonApiQuery $query Requested query
     * @param integer $total Total results before pagination
     * @return array
     */
    private function getBlogPosts(JsonApiQuery $query, &$total) {
        // static data as an example
        $blogPosts = array(
            1 => array(
                'id' => 1,
                'title' => 'Lorum Ipsum',
                'author' => array(
                    'id' => 1,
                    'name' => 'John Doe',
                ), 
                'tags' => array(
                    1 => array(
                        'id' => 1,
                        'name' => 'lorum',
                    ),
                    2 => array(
                        'id' => 2,
                        'name' => 'ipsum',
                    ),                    
                ),
            ),
            // ...
        );
        
        // count the total
        $total = count($blogPosts);
        
        // apply pagination
        $blogPosts = array_slice($blogPosts, $query->getOffset(), $query->getLimit(10, 100));

        // return the result
        return $blogPosts;
    }

}

实现资源适配器

上一个示例中博客文章的资源适配器可能如下所示

<?php

include ride\library\http\jsonapi\JsonApiDocument;
include ride\library\http\jsonapi\JsonApiResourceAdapter;

/**
 * Resource adapter for a blog post
 */
class BlogPostResourceAdapter implements JsonApiResourceAdapter {
   
    /**
     * Type of this resource
     * @var string
     */ 
    const TYPE = 'blog-posts';
    
    /**
     * Gets a resource instance for the provided model data
     * @param mixed $data Data to adapt
     * @param ride\library\http\jsonapi\JsonApiDocument $document Requested document
     * @param string $relationshipPath dot-separated list of relationship names
     * @return ride\library\http\jsonapi\JsonApiResource
     */
    public function getResource($data, JsonApiDocument $document, $relationshipPath = null) {
        $api = $document->getApi();
        $query = $document->getQuery();

        // create the resource for the entry        
        $resource = $api->createResource(self::TYPE, $data['id']);
        $resource->setLink('self', 'http://your-resource-url');
        
        // check for an attribute and set when requested
        if ($query->isFieldRequested(self::TYPE, 'title')) {
            $resource->setAttribute('title', $data['title']);
        }

        // check for a relationship and set when requested        
        if ($query->isFieldRequested(self::TYPE, 'author') && $query->isIncluded($relationshipPath)) {
            // append the field to the relationship path
            $fieldRelationshipPath = ($relationshipPath ? $relationshipPath . '.' : '') . 'author';
            
            // retrieve the resource
            $peopleResourceAdapter = $api->getResourceAdapter('people');
            $author = $peopleResourceAdapter->getResource($data['author'], $document, $fieldRelationshipPath);
            
            // create the relationship 
            $relationship = $api->createRelationship();
            $relationship->setResource($author);
            $relationship->setLink('self', 'http://your-relationship-url');
            $relationship->setLink('related', 'http://your-related-url');
                        
            // add the relationship to your resource
            $resource->setRelationship('author', $relationship);
        }        
        
        // set a relationship collection value        
        if ($query->isFieldRequested(self::TYPE, 'tags') && $query->isIncluded($relationshipPath)) {
            $fieldRelationshipPath = ($relationshipPath ? $relationshipPath . '.' : '') . 'tags';
            $tagResourceAdapter = $api->getResourceAdapter('tags');
            
            $tags = $data['tags'];
            foreach ($tags as $tag) {
                $tags[$tagIndex] = $tagResourceAdapter->getResource($tag, $document);
            }
            
            $relationship = $api->createRelationship();
            $relationship->setResourceCollection($tags);
            $relationship->setLink('self', 'http://your-relationship-url');
            $relationship->setLink('related', 'http://your-related-url');
                                    
            $resource->setRelationship('tags', $relationship);
        }
        
        // return the resource
        return $resource;
    }
    
}

实现

对于更多示例,您可以检查以下库的实现

安装

您可以使用 Composer 来安装此库。

composer require ride/lib-http-jsonapi