You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP 8.1+Symfony5.4下如何组合Swagger属性为自定义属性?

可行,实现步骤如下

PHP 8.1完全支持自定义属性,结合NelmioApiDocBundle的扩展机制,你可以轻松实现类似NestJS的装饰器组合效果,把重复的Swagger注解封装成一个自定义属性。

1. 创建自定义属性类

首先定义一个SwaggerUtils属性,接收标签参数,同时预留开关控制是否包含默认响应:

// src/Annotation/SwaggerUtils.php
namespace App\Annotation;

use Attribute;

#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
class SwaggerUtils
{
    public function __construct(
        public string $tag,
        public bool $include400 = true,
        public bool $include401 = true,
        public bool $include403 = true,
        public bool $requireBearer = true
    ) {}
}

2. 编写注解处理器

实现NelmioApiDocBundle的注解处理器接口,当识别到SwaggerUtils属性时,自动生成对应的OA响应、安全验证和标签注解:

// src/Handler/SwaggerUtilsHandler.php
namespace App\Handler;

use App\Annotation\SwaggerUtils;
use Nelmio\ApiDocBundle\Annotation\AnnotationHandlerInterface;
use Nelmio\ApiDocBundle\Annotation\Security;
use OpenApi\Annotations as OA;
use ReflectionMethod;

class SwaggerUtilsHandler implements AnnotationHandlerInterface
{
    public function handle($annotation, ReflectionMethod $method, array $annotations, \Nelmio\ApiDocBundle\Describer\ModelRegistry $registry): array
    {
        if (!$annotation instanceof SwaggerUtils) {
            return $annotations;
        }

        $newAnnotations = [];

        // 添加指定标签
        $newAnnotations[] = new OA\Tag(name: $annotation->tag);

        // 添加Bearer安全验证
        if ($annotation->requireBearer) {
            $newAnnotations[] = new Security(name: 'Bearer');
        }

        // 生成400响应
        if ($annotation->include400) {
            $newAnnotations[] = new OA\Response(
                response: 400,
                description: 'Bad parameters',
                content: new OA\JsonContent(example: ['code' => 400, 'message' => 'Bad Request', 'appCode' => 5000])
            );
        }

        // 生成401响应
        if ($annotation->include401) {
            $newAnnotations[] = new OA\Response(
                response: 401,
                description: 'JWT Token not found (appCode = 5001) or expired (appCode = 5002)',
                content: new OA\JsonContent(example: ['code' => 401, 'message' => 'JWT Token not found', 'appCode' => 5001])
            );
        }

        // 生成403响应
        if ($annotation->include403) {
            $newAnnotations[] = new OA\Response(
                response: 403,
                description: 'Insufficient privileges',
                content: new OA\JsonContent(example: ['code' => 403, 'message' => 'Forbidden', 'appCode' => 5003])
            );
        }

        // 合并原有注解与自动生成的注解
        return array_merge($annotations, $newAnnotations);
    }

    public function supports($annotation): bool
    {
        return $annotation instanceof SwaggerUtils;
    }
}

3. 注册处理器服务

在config/services.yaml中注册处理器,让NelmioApiDocBundle能识别并调用它:

services:
    App\Handler\SwaggerUtilsHandler:
        tags:
            - { name: nelmio_api_doc.annotation_handler }

4. 使用自定义属性

现在控制器方法只需一行注解就能替代原来的5个:

#[App\Annotation\SwaggerUtils(tag: 'User')]
public function getUserAction()
{
    // 业务逻辑
}

如果需要灵活控制(比如不需要400响应),可以传入参数:

#[App\Annotation\SwaggerUtils(tag: 'User', include400: false)]

原理说明

NelmioApiDocBundle在生成API文档时,会遍历所有注册的annotation_handler。当处理器检测到SwaggerUtils属性时,会自动生成对应的OpenAPI注解并合并到注解列表中,最终效果和手动编写所有注解完全一致。

内容的提问来源于stack exchange,提问作者Taine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 13:02:34