Schema definition name uses a validation groups generator's service id as a literal group (since #8595)

オープン
#8,815 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 2 日以内に返信

まだ誰も着手していません。

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
66/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
php, symfony

調査の方向性

Start with JsonSchema\DefinitionNameFactory::getValidationGroupsPart() and compare its handling of a string group value with the validator behavior described in the issue. Reproduce by exporting OpenAPI with the shown generator service id in validationContext.groups; done when the definition name no longer includes that service id while its suffix agrees with the constraints used in the schema.

索引モデルが issue の本文から書いたものです。

説明

Q A
API Platform version(s) affected 4.4.6
Symfony 8.1.11
PHP 8.4
Description

Since #8595, DefinitionNameFactory appends an operation's validation groups to the JSON Schema definition name. When validationContext.groups is the service id of a validation groups generator (a string naming a service tagged api_platform.validation_groups_generator), the name factory treats that string as a literal group name. The service id ends up in the definition name.

The validator side handles the same value differently, so the name no longer describes the constraints in the schema:

Where What it does with 'groups' => BookGroupsGenerator::class
JsonSchema\DefinitionNameFactory::getValidationGroupsPart() (v4.4.6, line 112) Wraps the string in an array and flattens it, so the name gets validation.App.Validator.BookGroupsGenerator
Symfony\Validator\Metadata\Property\ValidatorPropertyMetadataFactory::getValidationGroups() (line 155) Uses validation_groups only when it is an array or a GroupSequence, so a string falls back to the class default group Default
Symfony\Validator\Validator::validate() (line 38) At runtime, resolves the service id from the container and calls it with the object

The docblock on getValidationGroupsPart() says it mirrors ValidatorPropertyMetadataFactory::getValidationGroups() "so a definition name and the constraints it labels always agree". For a service id they do not agree: the name claims the generator's groups, while the schema's constraints come from Default.

A group-provider callable is already skipped (\is_callable($groups) returns ''). A generator service id is just as dynamic, because only the validator can compute its groups. But it reaches the flattening code and becomes part of the name.

How to reproduce
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Post;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Validator\Constraints as Assert;

#[AutoconfigureTag('api_platform.validation_groups_generator')]
final class BookGroupsGenerator
{
    public function __invoke(Book $book): array
    {
        return ['Default', 'book:strict'];
    }
}

#[ApiResource(operations: [
    new Post(
        denormalizationContext: ['groups' => ['book:write']],
        validationContext: ['groups' => BookGroupsGenerator::class],
    ),
])]
class Book
{
    #[Groups(['book:write'])]
    #[Assert\NotBlank(groups: ['book:strict'])]
    public ?string $title = null;
}

Export the OpenAPI document (bin/console api:openapi:export) and look at the input definition for POST /books.

Expected

One of these:

  • A generator service id is handled like a callable: no validation suffix, because the groups are only known at validation time.
  • Or the name and the constraints are built from the same resolved groups.
Actual

The definition is named Book-book.write_validation.App.Validator.BookGroupsGenerator, and its constraints are built from the Default group. On 4.3 the name was Book-book.write, so every generated client renames the type on upgrade, and the new name describes groups the schema does not use.

Possible solution

In getValidationGroupsPart(), return '' for a string value that is not an array or GroupSequence. That matches ValidatorPropertyMetadataFactory, which ignores such a value and uses Default. A string that names a single static group would then lose its suffix as well. If that matters, the check could ask the container whether the string is a service id, the way Validator::validate() does.

Workaround

Pin the name with SchemaFactory::OPENAPI_DEFINITION_NAME in the operation's normalization and denormalization contexts. #8595 notes that the explicit override still wins.

主要言語
PHP
スター
2.6k
フォーク
988
平均マージ
4日 10時間
マージ済み PR(30日)
114

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

api-platform/core のほかの issue

api-platform/core の issue をすべて見る

似ている issue

PHP の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。