Symfony3 表单组件试图将 null 传递给 PHP 7 中的类型提示方法

Symfony3 Form component trying to pass null to a type hinted method in PHP 7

在我的实体 class 中,我已经为 setter 和 return 类型的 getter 定义了所有预期的参数类型。 后来,当我有一个使用上述 class 的表单时,如果表单中的某些字段为空,我会收到错误消息,因为表单组件试图将 null 传递给 setter 而不是字符串。

提交表单时出现以下异常:

Expected argument of type "string", "NULL" given

500 Internal Server Error - InvalidArgumentException

vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php at line 254

抛出异常

有没有办法在将“null”值传递给对象之前将其转换为空字符串,并让验证器争论不休?

我在这里看到两个选项:

快速而简单 - 使传递给 setter 的参数可选:

public function setTitle(String $title = null)
{
    $this->title = $title;
    return $this;
}

可能更好 - 在 FormType 中使用 data transformer

数据转换器允许您在使用数据之前对其进行修改。

   $builder
    // ...
        ->add('title', 'text')
    // ...
    ;

    $builder->get('title')->addModelTransformer(new CallbackTransformer(
        function($originalInput){
            return $string;
        },
        function($submittedValue){ 
            // When null is cast to a string, it will be empty.
            return (string) $submittedValue;
        }
    ));

我之前发布过 使用此检索方法检索实体对象之前。看一个更复杂的例子是否有帮助。

如果实体 属性 不能 null并且您使用 PHP 7.1+),那么 [= =11=] 听起来更像是维护实体和表单之间直接数据绑定的肮脏且快速的解决方法(使用 Symfony 表单组件)。

更好的全局方法(在我看来)是使用 DTO(数据传输对象),这是一个简单的 POPO (Plain Old PHP Object) 来包含您的表单数据。

使用 DTO 将允许您在实体中保持严格的类型提示(不会丢失数据一致性)并且会解耦表单数据绑定(但是也来自您的实体的数据验证)。

DTO 允许重用并具有许多其他优点。

关于将 DTO 与 Symfony Forms 一起使用的一些有用参考资料: