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

API Platform生成TypeScript类型时ID等必填字段被标记为非必填的问题

API Platform/Symfony生成Swagger Schema时,ORM必填字段未标记为required的解决办法

问题场景

使用最新版API Platform/Symfony管理API,通过@rtk-query/codegen-openapi生成TypeScript类型时发现:ORM主键id、设置了nullable: false的关联字段createdBy等本该必填的字段,被标记为非必填;仅添加了#[Assert\NotNull]注解的date字段被识别为必填。Swagger Schema的required数组仅包含date,但这些字段在数据库层面是强制非空的。

生成的TypeScript类型

export type UserMeasurementJsonldUserMeasurementRead = {
     "@context"?:
     | string
     | {
           "@vocab": string;
           hydra: "http://www.w3.org/ns/hydra/core#";
           [key: string]: any;
        };
     "@id"?: string;
     "@type"?: string;
     id?: string;
     date: string;
     userDescription?: string | null;
     createdAt?: string;
     createdBy?: UserJsonldUserMeasurementRead;
};

对应的Swagger Schema片段

"UserMeasurement.jsonld-UserMeasurement.read":{
     "type":"object",
     "description":"",
     "deprecated":false,
     "properties":{
        "@id":{
           "readOnly":true,
           "type":"string"
        },
        "id":{
           "readOnly":true,
           "type":"string",
           "format":"uuid"
        },
        "date":{
           "type":"string",
           "format":"date-time"
        },
        "userDescription":{
           "type":[
              "string",
              "null"
           ]
        },
        "createdAt":{
           "type":"string",
           "format":"date-time"
        },
        "createdBy":{
           "$ref":"#\/components\/schemas\/User.jsonld-UserMeasurement.read"
        }
     },
     "required":[
        "date"
     ]
}

PHP实体代码

class UserMeasurement
{
    #[ORM\Id]
    #[ORM\Column(type: "uuid", unique: true)]
    #[ORM\GeneratedValue(strategy: "CUSTOM")]
    #[ORM\CustomIdGenerator(class: UuidGenerator::class)]
    #[Groups(groups: ['UserMeasurement:read'])]
    protected UuidInterface $id;

    #[ORM\Column(type: Types::DATE_MUTABLE, name: '_date')]
    //#[Assert\DateTime] // dump(assert non fonctionnel)
    #[Assert\NotNull]
    #[Groups(groups: ['UserMeasurement:read', 'UserMeasurement:write'])]
    private ?\DateTimeInterface $date = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    #[Localizable]
    #[Assert\NotBlank(allowNull: true)]
    #[Groups(groups: ['UserMeasurement:read', 'UserMeasurement:write'])]
    private ?string $userDescription = null;

    #[ORM\Column]
    #[Groups(groups: ['UserMeasurement:read'])]
    private ?\DateTimeImmutable $createdAt = null;

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(nullable: false)]
    #[Groups(groups: ['UserMeasurement:read'])]
    private ?User $createdBy = null;

    ...
}

解决方法

不需要给所有字段添加#[Assert\NotNull],API Platform默认仅将**验证约束(如Assert注解)**同步到Swagger的required数组,可通过以下两种方式让ORM层面的必填字段自动加入required:

1. 全局启用ORM验证同步

在config/packages/api_platform.yaml中开启orm_validations配置,自动将ORM非空约束映射为Swagger的必填字段:

api_platform:
    mapping:
        paths: ['%kernel.project_dir%/src/Entity']
    validator:
        enabled: true
        orm_validations: true

该配置会自动识别:

  • 主键字段(#[ORM\Id])
  • #[ORM\Column(nullable: false)]标记的字段
  • #[ORM\JoinColumn(nullable: false)]标记的关联字段

2. 给单个字段手动标记必填

如果不需要全局同步,可给特定字段添加#[ApiProperty(required: true)]注解:

use ApiPlatform\Metadata\ApiProperty;

class UserMeasurement
{
    #[ORM\Id]
    #[ORM\Column(type: "uuid", unique: true)]
    #[ORM\GeneratedValue(strategy: "CUSTOM")]
    #[ORM\CustomIdGenerator(class: UuidGenerator::class)]
    #[Groups(groups: ['UserMeasurement:read'])]
    #[ApiProperty(required: true)]
    protected UuidInterface $id;

    // ...

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(nullable: false)]
    #[Groups(groups: ['UserMeasurement:read'])]
    #[ApiProperty(required: true)]
    private ?User $createdBy = null;
}

注意事项

  • 主键字段默认在数据库层面必填,但API Platform不会自动将其加入required,需通过上述方式手动配置。
  • 对于ORM自动填充的字段(如createdAt,可通过实体构造函数赋值),也可使用同样方法标记为必填。

内容的提问来源于stack exchange,提问作者Gaylord.P

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 10:44:50