定制 nbo/rest-api-bundle 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

nbo/rest-api-bundle

Composer 安装命令:

composer require nbo/rest-api-bundle

包简介

Out of the box generic Symfony 5 REST API backend, transform any Doctrine entity and his relations onto API resources.

README 文档

README

This bundle is a generic REST API, easily create and configure your API resources using your Doctrine entities.

Latest Stable Version Minimum PHP Version Build Status

Setup

$ composer req nbo/restapibundle

Documentation

Getting started

First you need to compose your api. Add a config/packages/rest_api.yml configuration onto your project.

Here's an example for a simple REST API, with a "user" and a "page" resources.

rest_api:
  default_limit: 10
  default_offset: 0
  default_order: {'id':'desc'}
  resources:
    user:
      classname: 'App\Entity\User'
      methods:
        get:
          authenticated: true
          roles: ['ROLE_ADMIN']
        post:
          authenticated: true
          roles: ['ROLE_ADMIN']
        put:
          authenticated: true
          roles: ['ROLE_ADMIN']
        delete:
          authenticated: true
          roles: ['ROLE_ADMIN']
    page:
      classname: 'App\Entity\Page'
      methods:
        get: ~
        post:
          authenticated: true
          roles: ['ROLE_CMS']
        put:
          authenticated: true
          roles: ['ROLE_CMS']
        delete:
          authenticated: true
          roles: ['ROLE_CMS']

In this example, all resource endpoints need an authenticated user with specific roles, except the GET /page which is public.

Use cases

Endpoint that require authenticated users

To restrict an endpoint to authenticated users, regardless of their roles, juste use the authenticated option.

Endpoint that require authenticated users and one or more specific roles

To restrict an endpoint to authenticated users with one or more specific roles, juste use the roles array option with the needed role(s).

User scoped resource

Sometimes, you need to scope a specific resource at a user level, where users can only see their own resources. Use the owner_restricted option.to do so.

Public endpoints

By default with no option, the endpoint is public. No authentication is needed.

Update your Doctrine entities

The next step is to transform your Doctrine entities onto API resources.

Here's an example of the User entity transformed onto an API resource.

<?php

namespace App\Entity;

use App\Entity\Traits\TimestampableEntity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
use Nbo\RestApiBundle\Annotations\Resource;
use Nbo\RestApiBundle\Entity\AbstractResource;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @Resource(name="user")
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class User extends AbstractResource implements UserInterface
{
    const ROLE_ADMIN = 'ROLE_ADMIN';

    use TimestampableEntity;
    use SoftDeleteableEntity;

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     * @Groups("public")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     * @Groups("public")
     */
    private $email;

    /**
     * @ORM\Column(type="string", length=180)
     * @Groups("public")
     */
    private $displayName;

    /**
     * @ORM\Column(type="json")
     * @Groups("public")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     * @Groups("private")
     */
    private $password;

    public function __toString()
    {
        return (string) $this->getDisplayName();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    /**
     * @return string
     */
    public function getUsername(): string
    {
        return (string) $this->getEmail();
    }

    /**
     * @return mixed
     */
    public function getDisplayName(): ?string
    {
        return $this->displayName;
    }

    /**
     * @param mixed $displayName
     * @return User
     */
    public function setDisplayName($displayName = null)
    {
        $this->displayName = $displayName;
        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;
        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getPassword(): string
    {
        return (string) $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;
        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getSalt()
    {
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
    }
}

This is a simple User business object in a Symfony project. To turn it to an API resource, you just need to add the @Resource(name="your_api_resource_name") annotation.

Then you have to extends the AbstractResource or AbstractTranslatableResource abstract layers.

At this level, the API response is empty, to add data you need to add the @Groups("public") on the entity class members you want to expose.

This is it, your "user" resource REST API is now ready! An authenticated user with "ROLE_ADMIN" can now GET, POST, PUT or DELETE any user on "http://yourdomain/api/user" endpoint.

In a near future the @Group() annotation groups will become more flexible, to allow different levels of resource attributes access depending of the authenticated user roles.

Filter API resources

You can filter the API resources using the "q" query string parameter with the following filters:

Greater operator

Here we query all product resources, with a price greater than 150

GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"price":{">":150}}

Lesser operator

Here we query all product resources, with a price lesser than 150

GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"price":{"<":150}}

Equal operator

Here we query all product resources, with a price equal to 150

GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"price":{"=":150}}

Different operator

Here we query all product resources, with a color different than yellow

GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"color":{"!=":"yellow"}}

Is null operator

Here we query all product resources, with a category null

GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"category":{"IS NULL":"null"}}

Is not null operator

Here we query all product resources, with a category not null

GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"category":{"IS NOT NULL":"null"}}

LIKE operator

Here we query all product resources, with a name that start with "bag"

GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"name":{"LIKE":"bag%"}}

Here we query all product resources, with a name that end with "bag"

GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"name":{"LIKE":"%bag"}}

Here we query all product resources, with a name that contain "bag"

GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"name":{"LIKE":"%bag%"}}

Sort API resources

You can sort API resource by one or more fields, using the "sort" query parameter with the following syntax.

GET https://localhost:8000/api/media?page=1&limit=50&count=1&q={"platform":{"=":52}}&sort[updated]=desc&sort[otherfield]=asc

Count total API resources

To build a pagination system client side, you'll need to know for a given request how many API resources are available. To count API resources for a given request simply add the count query parameter.

GET http://localhost:8000/api/todo?page=5&limit=10&count=1

The API will add a "Count" response header, with the resources count for the given request.

Translatable resource

When your business object need to support i18n, you can GET, POST and PUT with a locale parameter:

GET http://localhost:8000/api/blog?page=5&limit=10

Become

GET http://localhost:8000/api/fr/blog?page=5&limit=10

To enable this behavior, you need to install the stof/doctrine-extensions-bundle, and update your Doctrine entity to extends the AbstractTranslatableResource layer and add the * @Gedmo\Translatable() annotation onto the translatable entity fields.

The stof/doctrine-extensions-bundle is the officially supported Doctrine extension bundle, but a future release will allow any Doctrine behavior extension.

nbo/rest-api-bundle 适用场景与选型建议

nbo/rest-api-bundle 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 157 次下载、GitHub Stars 达 1, 最近一次更新时间为 2019 年 10 月 20 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「json」 「xml」 「rest」 「api」 「doctrine」 「backend」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 nbo/rest-api-bundle 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 nbo/rest-api-bundle 我们能提供哪些服务?
定制开发 / 二次开发

基于 nbo/rest-api-bundle 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 157
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 2
  • 点击次数: 13
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: GPL-3.0
  • 更新时间: 2019-10-20