【发布时间】:2016-01-26 08:00:52
【问题描述】:
我有 Customer 实体和两个一对多关系 CustomerPhone 和 CustomerAddress。
客户实体有 addPhone/removePhone 和 addAddress/removeAddress "adders"。
CustomerType 集合选项对于两个集合都具有 'by_reference' => false。
实体函数 addPhone/removePhone 和 addAddress/removeAddress 在表单提交后没有被调用,所以 CustomerPhone 和 CustomerAddress 在持久化后没有父 id。
为什么在提交表单时不会调用 addPhone/removePhone 和 addAddress/removeAddress?
UPD 1.
在@Baig suggestion 之后,现在我调用了 addPhone/removePhone “adders”,但没有调用 addAddress/removeAddress。不知道为什么,因为它们是相同的。
# TestCustomerBundle/Entity/Customer.php
/**
* @var string
*
* @ORM\OneToMany(targetEntity="CustomerPhone", mappedBy="customerId", cascade={"persist"}, orphanRemoval=true)
*/
private $phone;
/**
* @var string
*
* @ORM\OneToMany(targetEntity="CustomerAddress", mappedBy="customerId", cascade={"persist"}, orphanRemoval=true)
*/
private $address;
同一个文件“adders”
# TestCustomerBundle/Entity/Customer.php
/**
* Add customer phone.
*
* @param Phone $phone
*/
public function addPhone(CustomerPhone $phone) {
$phone->setCustomerId($this);
$this->phone->add($phone);
return $this;
}
/**
* Remove customer phone.
*
* @param Phone $phone customer phone
*/
public function removePhone(CustomerPhone $phone) {
$this->phone->remove($phone);
}
/**
* Add customer address.
*
* @param Address $address
*/
public function addAddress(CustomerAddress $address) {
$address->setCustomerId($this);
$this->address->add($address);
return $this;
}
/**
* Remove customer address.
*
* @param Address $address customer address
*/
public function removeAddress(CustomerAddress $address) {
$this->address->remove($address);
}
关系:
# TestCustomerBundle/Entity/CustomerPhone.php
/**
* @ORM\ManyToOne(targetEntity="Customer", inversedBy="phone")
* @ORM\JoinColumn(name="customer_id", referencedColumnName="id")
**/
private $customerId;
#TestCustomerBundle/Entity/CustomerAddress.php
/**
* @ORM\ManyToOne(targetEntity="Customer", inversedBy="address")
* @ORM\JoinColumn(name="customer_id", referencedColumnName="id")
**/
private $customerId;
客户类型表单:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('phone', 'collection', array(
'type' => new CustomerPhoneType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'options' => array('label' => false)
))
->add('address', 'collection', array(
'type' => new CustomerAddressType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'options' => array('label' => false)
))
->add('submit', 'submit')
;
}
控制器。
# TestCustomerBundle/Controller/DefaultController.php
public function newAction(Request $request)
{
$customer = new Customer();
// Create form.
$form = $this->createForm(new CustomerType(), $customer);
// Handle form to store customer obect with doctrine.
if ($request->getMethod() == 'POST')
{
$form->bind($request);
if ($form->isValid())
{
/*$em = $this->get('doctrine')->getEntityManager();
$em->persist($customer);
$em->flush();*/
$request->getSession()->getFlashBag()->add('success', 'New customer added');
}
}
// Display form.
return $this->render('DeliveryCrmBundle:Default:customer_form.html.twig', array(
'form' => $form->createView()
));
}
UPD 2. 测试是否调用了 addAddress。
/**
* Add customer address.
*
* @param Address $address
*/
public function addAddress(Address $address) {
jkkh; // Test for error if method called. Nothing throws.
$address->setCustomerId($this);
$this->address->add($address);
}
UPD 3.
客户地址类型.php
<?php
namespace Delivery\CrmBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CustomerAddressType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('street')
->add('house')
->add('building', 'text', ['required' => false])
->add('flat', 'text', ['required' => false])
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Delivery\CrmBundle\Entity\CustomerAddress'
));
}
/**
* @return string
*/
public function getName()
{
return 'delivery_crmbundle_customeraddress';
}
}
CustomerPhoneType.php
<?php
namespace Delivery\CrmBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CustomerPhoneType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('number')
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Delivery\CrmBundle\Entity\CustomerPhone'
));
}
/**
* @return string
*/
public function getName()
{
return 'phone';
}
}
【问题讨论】:
-
您能更具体地说明您遇到的问题吗?很难说你认为问题出在哪里。
-
@kdbanman 实体函数 addPhone/removePhone 和 addAddress/removeAddress 在表单提交后不会被调用。它不像这里描述的那样工作 symfony.com/doc/current/cookbook/form/form_collections.html 因此,CustomerPhone 和 CustomerAddress 在持久化后没有父 ID。问题已更新。
-
您可以尝试删除
$em->persist($customer);,然后尝试。我也在使用集合类型,一切似乎都设置正确,虽然我使用的是yml,但这不应该有所作为。现在只是尝试删除$em->flush();我也不明白你的表单创建之上的所有内容的目的,我认为你不需要那个 -
当您使用
collectionType时,symfony 会自动查找add方法,因此您不必在控制器中指定该方法,因此我建议您删除上面的代码$form = $this->createForm(new CustomerType(), $customer);跨度> -
@Baig 谢谢。这得到了家长的帮助。现在我调用了 addPhone/removePhone,但没有调用 addAddress/removeAddress。 CustomerAddress 在没有客户 ID 的情况下仍然保存。有问题的控制器代码已更新。
标签: forms symfony collections doctrine