antoi/restify-bundle 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

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

antoi/restify-bundle

最新稳定版本:v0.0.2

Composer 安装命令:

composer require antoi/restify-bundle

包简介

Reusable Symfony bundle providing abstract REST CRUD services, entity hydration, and pick-based serialization.

README 文档

README

A reusable Symfony bundle providing a complete REST CRUD stack: abstract service, controller, repository, automatic entity hydration, and pick-based response enrichment.

Compatible with Symfony 6.4, 7.x, and 8.x — requires PHP 8.2+.

Installation

composer require antoi/restify-bundle

If you are not using Symfony Flex, register the bundle manually:

// config/bundles.php
return [
    Antoi\RestifyBundle\RestifyBundle::class => ['all' => true],
];

Full wiring example (User resource)

1. Repository

use Antoi\RestifyBundle\Repository\AbstractRestRepository;

class UserRepository extends AbstractRestRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, User::class);
    }

    // Only these fields may be used as query-param filters
    protected function getFilterableFields(): array
    {
        return ['name', 'email', 'status', 'createdAt'];
    }

    // Eager-load these relations on every list query
    protected function getDefaultJoins(): array
    {
        return ['role'];
    }
}

2. Service

use Antoi\RestifyBundle\Service\AbstractRestService;

class UserService extends AbstractRestService
{
    protected function getEntityClass(): string { return User::class; }

    protected function getWritableFields(): array
    {
        return ['name', 'email', 'role', 'status'];
    }
}

Wire in config/services.yaml (needed because AbstractRestService takes a typed AbstractRestRepository):

App\Service\UserService:
  arguments:
    $repository: '@App\Repository\UserRepository'

3. Controller

use Antoi\RestifyBundle\Controller\AbstractRestController;

#[Route('/api/users')]
class UserController extends AbstractRestController
{
    public function __construct(
        SerializerInterface $serializer,
        ValidatorInterface  $validator,
        PickResolver        $pickResolver,
        UserService         $service,
    ) {
        parent::__construct($serializer, $validator, $pickResolver, $service);
    }

    protected function getReadGroups(): array  { return ['user:read']; }
    protected function getListGroups(): array  { return ['user:list']; }
}

That's it. Six endpoints are registered automatically.

Endpoints

Method Path Action Description
GET / list() Paginated, filterable list
GET /{id} show() Single resource
POST / create() Create + validate + persist
PUT /{id} update() Full replace + validate + persist
PATCH /{id} patch() Partial update + validate + save
DELETE /{id} delete() Remove

Query parameters

Pagination & sorting

GET /api/users?page=2&limit=10&sort=name,-createdAt
  • sort=nameORDER BY name ASC
  • sort=-createdAtORDER BY createdAt DESC
  • Multiple fields: sort=name,-createdAt

Filtering

Any query param not in [page, limit, sort, pick] is forwarded to the repository as a filter.

GET /api/users?status=active&createdAt_gte=2024-01-01&name_like=john

Supported operators (append as suffix):

Suffix SQL equivalent
(none) = :value
_gte >= :value
_gt > :value
_lte <= :value
_lt < :value
_neq != :value
_like LIKE %value%
_in IN (a, b, c)
=null IS NULL

Pick — extra properties outside serialization groups

GET /api/users/42?pick=ip,lastLogin.ip,roles.name

Enriches the serialized response with additional properties resolved from the entity:

  • ip$user->getIp()
  • lastLogin.ip$user->getLastLogin()->getIp() (deep traversal)
  • roles.name[$role->getName(), ...] for each role in the collection

Response shapes

Single resource

{
  "success": true,
  "data": { "id": 1, "name": "John" }
}

Paginated list

{
  "success": true,
  "data": [ ... ],
  "meta": { "total": 42, "page": 1, "limit": 20, "pages": 3 }
}

Validation error (422)

{
  "success": false,
  "message": "Validation failed.",
  "errors": {
    "email": ["This value is not a valid email address."]
  }
}

Not found (404)

{ "success": false, "message": "User with ID \"99\" was not found." }

Wire InvalidPayloadException (400) and ResourceNotFoundException (404) to your API error listener to produce these shapes automatically.

Components reference

Class Namespace Description
AbstractRestRepository …\Repository Paginator, dynamic filters, operator suffixes
AbstractRestService …\Service Decode → filter fields → hydrate → persist
AbstractRestController …\Controller Full CRUD actions, serialization, pick merging
EntityHydrator …\Service Scalar + datetime + ManyToOne + ManyToMany
PickResolver …\Service Dot-notation deep property resolver
ApiResponse …\DTO { success, data, message } envelope
PaginatedResponse …\DTO { success, data, meta } envelope
InvalidPayloadException …\Exception 400 — bad JSON or wrong field type
ResourceNotFoundException …\Exception 404 — entity not found

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-05-05

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固