Forms Symfony2嵌入表单无效,尽管cascade_验证为假
在FormContractType中,我需要与客户的关联,客户本身与公司和账单地址有关联。但是这3个嵌套实体的数据本身在合同视图中根本不应该是可编辑的。这就是为什么合同中的customer Manytone关系字段是隐藏的 但是,出于显示目的,我需要表单中的整个customer对象,包括基础公司和账单地址,但为只读。这就是为什么我在合同表单类型中添加了一个额外的字段customerFullObject——它没有映射=>false。因为它是一个未映射的字段,所以我通过表单事件设置数据 现在,当我编辑合同数据时,客户的公司地址和账单地址数据将无效。 如果我删除/注释整个customerFullObject部分,则一切正常 我不明白,未映射字段如何/为什么会更改实体的数据。 我怎样才能防止Symfony这样做?还是有更好的模式/方式来实现我的目标?我在文件里找不到任何东西 以下是为简洁起见从模型中删除名称空间的一些代码片段: Contract.php Customer.php ContractType.php CustomerType.phpForms Symfony2嵌入表单无效,尽管cascade_验证为假,forms,symfony,Forms,Symfony,在FormContractType中,我需要与客户的关联,客户本身与公司和账单地址有关联。但是这3个嵌套实体的数据本身在合同视图中根本不应该是可编辑的。这就是为什么合同中的customer Manytone关系字段是隐藏的 但是,出于显示目的,我需要表单中的整个customer对象,包括基础公司和账单地址,但为只读。这就是为什么我在合同表单类型中添加了一个额外的字段customerFullObject——它没有映射=>false。因为它是一个未映射的字段,所以我通过表单事件设置数据 现在,当我编
我对这种嵌入式表单没有太多经验,但您是否尝试过在这里传递克隆客户对象:$form->get'customerFullObject'->setData$event->getData->getCustomer;与其是未映射的客户,不如映射客户并显示为只读。或者,如果您不想显示,客户可能是一个隐藏字段。然后,控制器可以为合同设置客户,所有内容都应该很好地持久化。@lackovic10这会起作用,但对象相当大,克隆会产生相当大的影响overhead@geoB我已经为客户设置了一个映射字段,该字段被隐藏以设置合同和客户之间的关系。但是隐藏字段只有关于Id的信息。但是我还需要其余的信息,因为我想显示一些附加信息。
/**
* @ORM\Entity
*/
class Contract {
/**
* @var Customer
* @ORM\ManyToOne(targetEntity="Customer", inversedBy="contracts")
* @Assert\Type(type="Customer")
* @Assert\NotBlank(message = "customer.notBlank")
**/
private $customer;
// Other fields left out as irrelevant.
}
/**
* @ORM\Entity
*/
class Customer {
/**
* @var Company
* @ORM\OneToOne(targetEntity="Company")
* @Assert\NotBlank(message="company.notBlank")
**/
private $company;
/**
* @var Address
* @ORM\OneToOne(targetEntity="Address")
* @Assert\NotBlank(message="billingAddress.notBlank")
**/
private $billingAddress;
/**
* @var ArrayCollection
* @ORM\OneToMany(targetEntity="Contract", mappedBy="customer", orphanRemoval=true, cascade={"all"})
**/
private $contracts;
// Other fields left out as irrelevant.
}
class ContractType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add(
'customer',
'customerHiddenType',
array(
'label' => 'contract.customer',
)
);
$builder->add(
'customerFullObject',
'customerType',
array(
'cascade_validation' => false,
'mapped' => false
)
);
$builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$editMode = $form->getConfig()->getOption('editMode');
if (!empty($editMode) && $editMode === RequestAction::CREATE()) {
$form->remove('customerFullObject');
} else {
$form->get('customerFullObject')->setData($event->getData()->getCustomer());
}
}
);
// Other children left out as irrelevant.
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(
array(
'data_class' => 'Contract',
'cascade_validation' => true
)
);
}
public function getName() {
return 'contractType';
}
}
class CustomerType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add(
'company',
'companyType',
array(
'cascade_validation' => false,
'label' => 'customer.company'
)
);
$builder->add(
'billingAddress',
'addressType',
array(
'cascade_validation' => false,
'label' => 'customer.billingAddress'
)
);
// Other children left out as irrelevant.
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(
array(
'data_class' => 'Customer',
'cascade_validation' => true
)
);
}
public function getName() {
return 'customerType';
}
}