将类型化属性(PHP7.4)与Symfony表单一起使用
我使用DTO作为Symfony表单类型的将类型化属性(PHP7.4)与Symfony表单一起使用,symfony,Symfony,我使用DTO作为Symfony表单类型的数据类。当我在这些DTO中使用类型化属性(PHP7.4)时,有一件事对我不起作用 例如: class ProductDto { /* * @Assert\NotBlank */ public string $title; } 这通常看起来效果很好——如果用户提交的表单标题或描述为空,则验证开始,表单显示验证警告 但在创建表单(例如编辑表单)时添加数据时会出现问题: 最初,表单按预期显示,并使用Foo作为标题的值。当用户
数据类
。当我在这些DTO中使用类型化属性(PHP7.4)时,有一件事对我不起作用
例如:
class ProductDto
{
/*
* @Assert\NotBlank
*/
public string $title;
}
这通常看起来效果很好——如果用户提交的表单标题或描述为空,则验证开始,表单显示验证警告
但在创建表单(例如编辑表单)时添加数据时会出现问题:
最初,表单按预期显示,并使用Foo
作为标题的值。当用户清除标题
输入表单字段并提交表单时,会引发如下异常:
Typed property `App\Form\Dto\ProductDto::$title` must be string, null used
据我所知,这是因为在Form->handleRequest()
期间,标题在之前设置为“Foo”后被设置为空字符串(或null),对吗
有解决此问题的方法吗?由于PHP7.4引入了属性的类型暗示,因此为所有属性提供有效值尤其重要,以便所有属性都具有与其声明的类型匹配的值
从未分配过的属性没有空值,但它处于未定义状态,这将永远不会与任何声明的类型匹配。未定义!==空
以下是一个例子:
这就是我刚刚想到的:
DTO:
特点:
trait GenericSetterTrait
{
private function set(string $propertyName, $value): void
{
if ($value === null) {
unset($this->{$propertyName});
} else {
$this->{$propertyName} = $value;
}
}
}
似乎有效。你怎么认为?有异议吗?一种方法是将公共字符串更改为公共?字符串,使其可为空,另一种方法是将$title的默认值添加为空字符串公共字符串$title='
,另一种方法是添加构造函数并在其中设置属性值。@Slavian Thx。我认为?
不是最优的,对吗?空字符串确实是一个选项。您将如何处理例如public Foo$Foo代码>?这真的取决于上下文,如果我有一个属性,它是一个类,就像你给出的例子一样,我会想这个属性应该是null还是应该总是类,不管怎样。这实际上取决于您想要实现什么。表单字段上的'empty\u data'=>'
work@Jakumi'empty_data'=>'
似乎与@Assert\NotBlank
和字符串属性结合使用。但它不是一个选项,例如,public Foo$Foo代码>。谢谢,但是“在初始化之前不能被访问”不是我目前的问题。我认为这是某种哲学,在幕后可能是$this->createForm(ProductFormType::class,$productDto)代码>将影响空到$title
use GenericSetterTrait;
/**
* @Assert\NotBlank
*/
public string $title;
public function setTitle(?string $title): void
{
$this->set('title', $title);
}
/**
* @Assert\NotNull
*/
public Foo $foo;
public function setFoo(?Foo $foo): void
{
$this->set('foo', $foo);
}
trait GenericSetterTrait
{
private function set(string $propertyName, $value): void
{
if ($value === null) {
unset($this->{$propertyName});
} else {
$this->{$propertyName} = $value;
}
}
}