paknahad/jsonapi-bundle

jsonapi-bundle是一个Symfony包。使用woohoolabs/yin生成基于JsonApi.org的API最快的方法。

安装次数: 45,331

依赖项: 4

建议者: 0

安全性: 0

星标: 70

关注者: 4

分支: 25

开放问题: 18

类型:symfony-bundle

v5.0.0 2021-12-06 15:58 UTC

README

Latest Stable Version test workflow License: MIT Total Downloads

JsonApiBundle For Symfony

JsonApiBundle是一个Symfony包。使用JsonApiwoohoolabs/yin库生成API最快的方法。

安装

  1. 安装symfony

    composer create-project symfony/skeleton YOUR_PROJECT
    
  2. 安装maker bundle

    composer require symfony/maker-bundle phootwork/collection --dev
    
  3. 安装此包

    composer require paknahad/jsonapi-bundle
    

    对于Symfony 4使用

    composer require paknahad/jsonapi-bundle:^3.1
    
  4. 将以下行添加到config/bundles.php

    Paknahad\JsonApiBundle\JsonApiBundle::class => ['all' => true],
    

用法

  1. 使用以下命令逐个生成实体

    bin/console make:entity
    

    例如,Book和Author实体如下所示

    use Doctrine\ORM\Mapping as ORM;
    class Book
    {
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(type="integer")
         */
        private $id;
    
        /**
         * @ORM\Column(type="string", length=255)
         */
        private $title;
    
        /**
         * @ORM\Column(type="string", length=20, nullable=true)
         */
        private $isbn;
    
        /**
         * @ORM\ManyToMany(targetEntity="App\Entity\Author", inversedBy="books")
         */
        private $authors;
     
        ... 
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
    class Author
    {
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(type="integer")
         */
        private $id;
    
        /**
         * @ORM\Column(type="string", length=255)
         * @Assert\NotBlank()
         * @Assert\Length(min=3)
         */
        private $name;
    
        /**
         * @ORM\ManyToMany(targetEntity="App\Entity\Book", mappedBy="authors")
         */
        private $books;
     
        ...
  2. 生成CRUD API

    bin/console make:api
    
  3. 您可以在以下路径找到生成的"collections",并在其中测试API

    collection/postman.json
    collection/swagger.yaml
    

特性

分页

http://example.com/books?page[number]=5&page[size]=30

排序

  • 按名称字段升序:http://example.com/books?sort=name
  • 按名称字段降序:http://example.com/books?sort=-name
  • 多个字段:http://example.com/books?sort=city,-name
  • 关系字段:http://example.com/books?sort=author.name

关系

http://example.com/books?include=authors

多个关系

http://example.com/books?include=authors.phones,publishers

搜索

由于JSON API规范没有确切指定过滤应该如何工作,可以使用不同的过滤方法。每种方法都提供了Finder服务。每个注册的Finder都将能够向搜索查询添加条件。如果您注册了多个Finder,它们将同时激活。这使您的API能够支持多种过滤方法。

基本Finder。

该库包含一个基本的Finder,提供简单的过滤功能。

此请求将返回所有作者姓名以"hamid"开头的书籍。

http://example.com/books?filter[authors.name]=hamid%

以下行有附加条件:标题中包含"php"的书籍。

http://example.com/books?filter[title]=%php%&filter[authors.name]=hamid%

在IndexAction上设置默认过滤器

使用$resourceCollection->getQuery()可以访问查询对象。使用"r"别名引用当前实体。在这个例子中,"r"指的是"ProjectEntity"。

use Symfony\Component\Routing\Annotation\Route;
class ProjectController extends Controller
{
    /**
     * @Route("/", name="projects_index", methods="GET")
     */
    public function index(ProjectRepository $projectRepository, ResourceCollection $resourceCollection): ResponseInterface
    {
        $resourceCollection->setRepository($projectRepository);

        $resourceCollection->getQuery()->where('r.user_id = :s1')->setParameter(...);
        $resourceCollection->handleIndexRequest();

        return $this->jsonApi()->respond()->ok(
            new ProjectsDocument(new ProjectResourceTransformer()),
            $resourceCollection
        );
    }

其他Finder

目前,以下Finder可以通过其他包获得

创建自定义Finder

Finder可以通过服务定义中的服务标签进行注册。必须将标签paknahad.json_api.finder添加到服务中,以便注册Finder。

示例

<service class="Paknahad\JsonApiBundle\Helper\Filter\Finder" id="paknahad_json_api.helper_filter.finder">
    <tag name="paknahad.json_api.finder" />
</service>

每个Finder都必须实现Paknahad\JsonApiBundle\Helper\Filter\FinderInterface接口。请参阅\Paknahad\JsonApiBundle\Helper\Filter\Finder以获取实现示例。

如果您需要更多对查找器的控制,您可以使用 \Paknahad\JsonApiBundle\Helper\Filter\FinderSupportsInterface 接口,并在 supports() 方法内部实现条件逻辑。

use Paknahad\JsonApiBundle\Helper\Filter\FinderSupportsInterface;
use Paknahad\JsonApiBundle\Helper\FieldManager;
use Symfony\Component\HttpFoundation\Request;

class CustomFinder implements FinderSupportsInterface
{
    public function supports(Request $request, FieldManager $fieldManager): bool
    {
        // based on some request data
        if ($request->query->has('some-flag')) {
            return true;
        }

        // based on document field manager
        if ($fieldManager->getRootEntity() === Author::class) {
            return true;
        }

        return false;
    }
}

验证

验证关联时出错

{
    "jsonapi": {
        "version": "1.0"
    },
    "errors": [
        {
            "detail": "Invalid value for this relation",
            "source": {
                "pointer": "/data/relationships/authors",
                "parameter": "1"
            }
        }
    ]
}

如果您在实体上定义了验证器,请验证属性。

{
    "jsonapi": {
        "version": "1.0"
    },
    "errors": [
        {
            "detail": "This value is too short. It should have 3 characters or more.",
            "source": {
                "pointer": "/data/attributes/name",
                "parameter": "h"
            }
        }
    ]
}

错误处理器

所有错误,如

  • 内部服务器错误(500)
  • 未找到(404)
  • 拒绝访问(403)

有如下响应

{
    "meta": {
        "code": 0,
        "message": "No route found for \"GET /book\"",
        "file": "/var/www/vendor/symfony/http-kernel/EventListener/RouterListener.php",
        "line": 139,
        "trace": [
            {
                "file": "/var/www/vendor/symfony/event-dispatcher/EventDispatcher.php",
                "line": 212,
                "function": "onKernelRequest"
            },
            {
                "file": "/var/www/vendor/symfony/event-dispatcher/EventDispatcher.php",
                "line": 44,
                "function": "doDispatch"
            },
            {
                "file": "/var/www/vendor/symfony/http-kernel/HttpKernel.php",
                "line": 125,
                "function": "dispatch"
            },
            {
                "file": "/var/www/vendor/symfony/http-kernel/HttpKernel.php",
                "line": 66,
                "function": "handleRaw"
            },
            {
                "file": "/var/www/vendor/symfony/http-kernel/Kernel.php",
                "line": 188,
                "function": "handle"
            },
            {
                "file": "/var/www/public/index.php",
                "line": 37,
                "function": "handle"
            }
        ]
    },
    "links": {
        "self": "/book"
    },
    "errors": [
        {
            "status": "404",
            "code": "NO_ROUTE_FOUND_FOR_\"GET_/BOOK\"",
            "title": "No route found for \"GET /book\""
        }
    ]
}

注意:仅在开发环境中填充“meta”字段。

配置

您可以使用以下选项配置此包

#config/packages/json_api.yaml

json_api:
    documentationSchema: 'openapi'
    controllerNamespace: 'Controller'

支持的文档模式是 openapiswagger。如果您想在不同命名空间中生成控制器,例如 Controller\Api,可以使用控制器命名空间配置选项。要前缀 Api 路由,可以使用 Symfony 路由配置。

#config/routes/annotations.yaml

api:
    resource: ../../src/Controller/Api
    type: annotation
    prefix: /api