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

Posted

技术标签:

【中文标题】Symfony3 表单组件试图将 null 传递给 PHP 7 中的类型提示方法【英文标题】:Symfony3 Form component trying to pass null to a type hinted method in PHP 7 【发布时间】:2016-10-01 08:05:22 【问题描述】:

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

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

“字符串”类型的预期参数,给定“NULL”

500 内部服务器错误 - InvalidArgumentException

vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php at line 254抛出异常

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

【问题讨论】:

【参考方案1】:

我在这里看到两个选项:

Quick and Dirty - 将传递给 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;
        
    ));

在使用此方法检索实体对象之前,我已经发布了another answer。看看是否有助于查看更复杂的示例。

【讨论】:

当使用第二种方式时,数据被转换,不抛出异常,但验证不再起作用。我尝试查看文档,但找不到原因。第一个选项有效,但正如你所说,它有点脏。 P.S.验证不仅仅适用于添加了数据转换器的那些字段。例如,如果我有一个“姓名”和“电子邮件”字段,并且我在“姓名”字段中添加了一个数据转换器,那么如果我将其留空并在“电子邮件”字段中放入一些无效的电子邮件地址,则会出现仅适用于“电子邮件”字段的验证错误消息。 @Angelov,响亮而清晰。不幸的是,自从我使用数据转换器和验证组件以来已经有一段时间了,我不记得它们的所有细微差别。我不知道我怎么能提供比我所能提供的更多的帮助。不过,查看其中一些验证规则可能会对问题有所帮助 - 如果我没记错的话,有多种方法可以使用验证器。 我在 github 上的 PHPDDD 项目上添加了一个问题,它提供了一种解决方法,至少可以用于使用 CQRS 处理命令:github.com/webdevilopers/php-ddd/issues/18【参考方案2】:

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

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

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

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

一些关于在 Symfony 表单中使用 DTO 的有用参考:

Avoiding Entities in Forms (by Iltar van der Berg) Rethinking Form Development (by Iltar van der Berg) Symfony Forms 101 (by Bernhard Schussek the creator of the Form component) Don't Use Entities in Symfony Forms. Use Custom Data Objects Instead Entities should always be valid

【讨论】:

以上是关于Symfony3 表单组件试图将 null 传递给 PHP 7 中的类型提示方法的主要内容,如果未能解决你的问题,请参考以下文章

React:我们可以将 2 个表单从 2 个不同的子组件传递给父组件,并使用父组件内的按钮提交它们吗?

Symfony 3 - 无法将 token_storage 传递给订阅者

无法将选中的值从自定义复选框组件传递给父组件

将可变表单刀片模板传递给vue组件

将表单传递给 AngularJS 组件进行验证

如何将 Angular 2 表单输入传递给打字稿组件?