Symfony Forms:CollectionType - 不要将 null 转换为空数组

Symfony Forms: CollectionType - Don't transform null to empty array

我们 API 使用 Symfony Forms 来验证请求数据。目前我们正面临 CollectionType 的问题,它将提供的值 null 转换为空数组 [].

因为区分用户供应 null 或空数组对我来说很重要,所以我想禁用此行为。

我已经尝试将 'empty_data' 设置为 null - 不幸的是没有成功。

我的字段配置如下:

$builder->add(
    'subjects',
    Type\CollectionType::class,
    [
        'entry_type'    => Type\IntegerType::class,
        'entry_options' => [
            'label'     => 'subjects',
            'required'  => true,
            'empty_data' => null,
        ],
        'required'   => false,
        'allow_add'  => true,
        'empty_data' => null,
    ]
);

表单的处理方式如下:

$data = $apiRequest->getData();

$form = $this->formFactory->create($formType, $data, ['csrf_protection' => false, 'allow_extra_fields' => true]);
$form->submit($data);

$formData = $form->getData();

当前行为是:

输入$data=>{ 'subjects' => null }

输出$formData=>{ 'subjects' => [] }

我想要的行为是:

输入$data=>{ 'subjects' => null }

输出$formData=>{ 'subjects' => null }

经过多次尝试,我终于找到了解决方案,方法是创建 From Type Extension in combination with a Data Transformer

通过创建此表单类型扩展,我能够扩展 CollectionType FormType 的默认配置。这样我就可以设置自定义构建 ModelTransformer 来处理我想要的行为。

这是我的表单类型扩展:

class KeepNullFormTypeExtension extends AbstractTypeExtension
{

    public static function getExtendedTypes(): iterable
    {
        return [CollectionType::class];
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        $builder->addModelTransformer(new KeepNullDataTransformer());
    }

}

这个需要在您的 service.yml 中使用 'form.type_extension' 标签注册:

PrivateApiBundle\Form\Extensions\KeepNullFormTypeExtension:
    class: PrivateApiBundle\Form\Extensions\KeepNullFormTypeExtension
    tags: ['form.type_extension']

Please note that you still use the CollectionType in your FormType and not the KeepNullFormTypeExtension as Symfony takes care about the extending...

KeepNullFormTypeExtension 中,您可以看到我使用 addModelTransformer 设置了一个自定义模型转换器,名为 KeepNullDataTransformer

KeepNullDataTransformer 负责将输入 null 保持为输出值——它看起来像这样:

class KeepNullDataTransformer implements DataTransformerInterface
{
    protected $initialInputValue = 'unset';

    /**
     * {@inheritdoc}
     */
    public function transform($data)
    {
        $this->initialInputValue = $data;
        return $data;
    }

    /**
     * {@inheritdoc}
     */
    public function reverseTransform($data)
    {
        return ($this->initialInputValue === null) ? null : $data;
    }
}

就是这样 - 这样,null 类型的输入将保持为 null

可以在链接的 Symfony 文档中找到有关此的更多详细信息: