1

I have 2 ORM entities (Customer and Address) which I want to combine into one form. When a new Customer is created also an new Address must be created (with type is set to 'invoice' by default)

My current code is like this.

Entities

|Customers| -1----N-> |Address|

class Customer
{
...

/**
 * @ORM\OneToMany(targetEntity="Address", mappedBy="customer")
 */
protected $addresses;
...
}

class Address
{
...
/**
 * @var string
 *
 * @ORM\Column(name="type", type="string", length=255)
 */
private $type; // (Invoice / Delivery)

/**
 * @ORM\ManyToOne(targetEntity="Customer", inversedBy="addresses")
 * @ORM\JoinColumn(name="customer_id", referencedColumnName="id")
 */
protected $customer;
...
}

The Controllers actions

/**
 * Creates a new Customer entity.
 *
 * @Route("/new", name="customer_new")
 * @Method({"GET", "POST"})
 */
public function newAction(Request $request)
{
    $customer = new Customer();
    $form = $this->createForm('Rekursief\CrmBundle\Form\CustomerType', $customer);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($customer);
        $em->flush();

        return $this->redirectToRoute('customer_show', array('id' => $customer->getId()));
    }

    return $this->render('customer/new.html.twig', array(
        'customer' => $customer,
        'form' => $form->createView(),
    ));
}
/**
 * Creates a new Address entity.
 *
 * @Route("/new", name="address_new")
 * @Method({"GET", "POST"})
 */
public function newAction(Request $request)
{
    $address = new Address();
    $form = $this->createForm('Rekursief\CrmBundle\Form\AddressType', $address);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($address);
        $em->flush();

        return $this->redirectToRoute('address_show', array('id' => $address->getId()));
    }

    return $this->render('address/new.html.twig', array(
        'address' => $address,
        'form' => $form->createView(),
    ));
}

Form types

    class CustomerType extends AbstractType
    {
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('firstname')
            ->add('lastname')
            ->add('telephone')
            ->add('mobilephone')
            ->add('email')
        ;

        $builder->add('type', ChoiceType::class, array(
            'choices'  => array(
                'Corporate' => 'corporate',
                'Private' => 'private',
            ),
            'data' => 'corporate',
        ));
    }
    }
    class AddressType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('street')
            ->add('number')
            ->add('box')
            ->add('state')
            ->add('country')
            ->add('city')
            ->add('postalcode')
            ->add('customer')
        ;

        $builder->add('type', ChoiceType::class, array(
            'choices'  => array(
                'Invoice' => 'invoice',
                'Delivery' => 'delivery',
            ),
            'data' => 'invoice',
        ));
    }
}

The chapter in the symfony book on Embedding form collections returned an Address form for every related address stored in the database. But when creating a new Customer which doesn't have any related Addresses no (address)form elements are shown. http://symfony.com/doc/current/cookbook/form/form_collections.html

An other option I've found didn't resolve without issues. How to merge 2 form in Symfony2

Community
  • 1
  • 1
kim.kaho
  • 43
  • 1
  • 8
  • Form collections are not going to add a form in no entity exists. You need to either create the address and add to your new customer in your controller or create the address in your customer's constructor. – Cerad Feb 08 '16 at 14:48
  • What do you mean by "create your address in your customer's constructor"? – kim.kaho Feb 08 '16 at 18:49

1 Answers1

1

Assume that we have a business rule which states that every customer has at least one address. We can implement this rule by creating an address in the customer's constructor.

class Customer
{
  public function __construct()
  {
    $this->addresses = new ArrayCollection();
    $address = new Address();
    $this->addAddress($address);
  }
  public function addAddress(Address $address)
  {
    $this->addresses[] = $address;
    $address->setCustomer($customer);
  }
Cerad
  • 48,157
  • 8
  • 90
  • 92
  • Now it creates an empty address reference but is it possible to save values out a (merged - customer & address) form? Sorry if this are basics but I'm new in symfony. – kim.kaho Feb 09 '16 at 07:49
  • You probably need to work you way through the examples in the docs. Lots of little stuff to learn. cascade=persist might help. http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations – Cerad Feb 09 '16 at 14:23