无法将实体转换为表单中使用的不可变值对象字段
Cannot transform an entity to an immutable Value Object field used in form
我在处理相当复杂的表单时遇到了问题。这种形式的子项是一个值对象,与在条令文档中可以找到的内容非常相似(即地址值对象,带有文本字段和国家/地区实体字段)。我可以毫不费力地显示地址值对象的每个字段的表单,但是当我提交它时,抛出一个 属性 访问异常,说既没有 属性 国家,也没有任何 setter 方法在值对象上。由于值对象是不可变的,因此预计会出现此异常。
$addressFormBuilder = $app['form.factory']->createNamedBuilder('address', 'form', new Address('street','postalCode','city','region',$country_1), [
'data_class' => 'Address'
]);
$addressFormBuilder
->add('street', 'text', ['constraints' => [new Assert\NotBlank ,new Assert\Length(['max' => 50])]])
->add('postal_code', 'text', ['constraints' => [new Assert\NotBlank ,new Assert\Length(['max' => 50])]])
->add('city', 'text', ['constraints' => [new Assert\NotBlank ,new Assert\Length(['max' => 50])]])
->add('region', 'text', ['constraints' => [new Assert\NotBlank ,new Assert\Length(['max' => 50])]])
->add('country', 'entity', [
'class' => 'Countries',
'choice_label' => 'label',
'em' => $this->em,
'placeholder' => ''
]);
$addressFormBuilder->addModelTransformer(new CallbackTransformer(function($originalDescription) {
return $originalDescription;
}, function($submittedDescription) {
// Exception thrown before this part
var_dump($submittedDescription);exit;
return new Addresses(null, null, null, null, null);
}));
问题实际上是我无法将提交的地址转换为新地址(处理不可变值对象的唯一方法)。由于转换器在转换之前处理提交的实体,因此在尝试将修改后的国家/地区实体设置为原始地址之后,我添加到地址字段的转换器可能被调用得太晚了。
所以我想知道是否有办法处理这个用例?
Symfony 的表单并非设计用于将不可变对象作为实体处理,因此当您尝试这样做时会遇到这个问题。
无论如何,表单的创建者自己已经发布了解决这个问题的方法:https://webmozart.io/blog/2015/09/09/value-objects-in-symfony-forms/
归结为:使用数据转换器
public function mapDataToForms($data, $forms)
{
$forms = iterator_to_array($forms);
$forms['amount']->setData($data ? $data->getAmount() : 0);
$forms['currency']->setData($data ? $data->getCurrency() : 'EUR');
}
和
public function mapFormsToData($forms, &$data)
{
$forms = iterator_to_array($forms);
$data = new Money(
$forms['amount']->getData(),
$forms['currency']->getData()
);
}
我在处理相当复杂的表单时遇到了问题。这种形式的子项是一个值对象,与在条令文档中可以找到的内容非常相似(即地址值对象,带有文本字段和国家/地区实体字段)。我可以毫不费力地显示地址值对象的每个字段的表单,但是当我提交它时,抛出一个 属性 访问异常,说既没有 属性 国家,也没有任何 setter 方法在值对象上。由于值对象是不可变的,因此预计会出现此异常。
$addressFormBuilder = $app['form.factory']->createNamedBuilder('address', 'form', new Address('street','postalCode','city','region',$country_1), [
'data_class' => 'Address'
]);
$addressFormBuilder
->add('street', 'text', ['constraints' => [new Assert\NotBlank ,new Assert\Length(['max' => 50])]])
->add('postal_code', 'text', ['constraints' => [new Assert\NotBlank ,new Assert\Length(['max' => 50])]])
->add('city', 'text', ['constraints' => [new Assert\NotBlank ,new Assert\Length(['max' => 50])]])
->add('region', 'text', ['constraints' => [new Assert\NotBlank ,new Assert\Length(['max' => 50])]])
->add('country', 'entity', [
'class' => 'Countries',
'choice_label' => 'label',
'em' => $this->em,
'placeholder' => ''
]);
$addressFormBuilder->addModelTransformer(new CallbackTransformer(function($originalDescription) {
return $originalDescription;
}, function($submittedDescription) {
// Exception thrown before this part
var_dump($submittedDescription);exit;
return new Addresses(null, null, null, null, null);
}));
问题实际上是我无法将提交的地址转换为新地址(处理不可变值对象的唯一方法)。由于转换器在转换之前处理提交的实体,因此在尝试将修改后的国家/地区实体设置为原始地址之后,我添加到地址字段的转换器可能被调用得太晚了。
所以我想知道是否有办法处理这个用例?
Symfony 的表单并非设计用于将不可变对象作为实体处理,因此当您尝试这样做时会遇到这个问题。
无论如何,表单的创建者自己已经发布了解决这个问题的方法:https://webmozart.io/blog/2015/09/09/value-objects-in-symfony-forms/
归结为:使用数据转换器
public function mapDataToForms($data, $forms)
{
$forms = iterator_to_array($forms);
$forms['amount']->setData($data ? $data->getAmount() : 0);
$forms['currency']->setData($data ? $data->getCurrency() : 'EUR');
}
和
public function mapFormsToData($forms, &$data)
{
$forms = iterator_to_array($forms);
$data = new Money(
$forms['amount']->getData(),
$forms['currency']->getData()
);
}