Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony 2 Embedded forms using one to many db relationship

I'm have a problem embedding forms from different entities in one form, my form is being displayed with firstname [input] lastname [input] address - but the address has no input next to it.

Basically I want to create a form where the user can add first name, last name, address1, address2, city, country ect and submit it it as one, although it's different tables.

The main form is no problem the only issue I'm having is with the second embedded form. Any help would be greatly appreciated.

Here is my code:

Member class:

namespace Pomc\MembersBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* Pomc\MembersBundle\Entity\Member
*/
class Member
{
/**
 * @var integer $id
 */
private $id;

/**
 * @var string $firstName
 */
private $firstName;

/**
 * @var string $lastName
 */
private $lastName;

/**
 * @var Pomc\MembersBundle\Entity\Address
 */
private $address;

/**
 * @var Pomc\MembersBundle\Entity\Telephone
 */
private $telephone;

public function __construct()
{
    $this->address = new \Doctrine\Common\Collections\ArrayCollection();
    $this->telephone = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Get id
 *
 * @return integer 
 */
public function getId()
{
    return $this->id;
}

/**
 * Set firstName
 *
 * @param string $firstName
 */
public function setFirstName($firstName)
{
    $this->firstName = $firstName;
}

/**
 * Get firstName
 *
 * @return string 
 */
public function getFirstName()
{
    return $this->firstName;
}

/**
 * Set lastName
 *
 * @param string $lastName
 */
public function setLastName($lastName)
{
    $this->lastName = $lastName;
}

/**
 * Get lastName
 *
 * @return string 
 */
public function getLastName()
{
    return $this->lastName;
}

/**
 * Add address
 *
 * @param Pomc\MembersBundle\Entity\Address $address
 */
public function addAddress(\Pomc\MembersBundle\Entity\Address $address)
{
    $this->address[] = $address;
}

/**
 * Get address
 *
 * @return Doctrine\Common\Collections\Collection 
 */
public function getAddress()
{
    return $this->address;
}

/**
 * Add telephone
 *
 * @param Pomc\MembersBundle\Entity\Telephone $telephone
 */
public function addTelephone(\Pomc\MembersBundle\Entity\Telephone $telephone)
{
    $this->telephone[] = $telephone;
}

/**
 * Get telephone
 *
 * @return Doctrine\Common\Collections\Collection 
 */
public function getTelephone()
{
    return $this->telephone;
}
}

Here is the address class:

namespace Pomc\MembersBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Pomc\MembersBundle\Entity\Address
 */
class Address
{
    /**
     * @var integer $id
     */
    private $id;

    /**
     * @var string $addressType
     */
    private $addressType;

    /**
     * @var string $firstLine
     */
    private $firstLine;

    /**
     * @var string $secondLine
     */
    private $secondLine;

    /**
     * @var string $city
     */
    private $city;

    /**
     * @var string $postCode
     */
    private $postCode;

    /**
     * @var string $country
     */
    private $country;

    /**
     * @var Pomc\MembersBundle\Entity\Member
     */
    private $member;


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set addressType
     *
     * @param string $addressType
     */
    public function setAddressType($addressType)
    {
        $this->addressType = $addressType;
    }

    /**
     * Get addressType
     *
     * @return string 
     */
    public function getAddressType()
    {
        return $this->addressType;
    }

    /**
     * Set firstLine
     *
     * @param string $firstLine
     */
    public function setFirstLine($firstLine)
    {
        $this->firstLine = $firstLine;
    }

    /**
     * Get firstLine
     *
     * @return string 
     */
    public function getFirstLine()
    {
        return $this->firstLine;
    }

    /**
     * Set secondLine
     *
     * @param string $secondLine
     */
    public function setSecondLine($secondLine)
    {
        $this->secondLine = $secondLine;
    }

    /**
     * Get secondLine
     *
     * @return string 
     */
    public function getSecondLine()
    {
        return $this->secondLine;
    }

    /**
     * Set city
     *
     * @param string $city
     */
    public function setCity($city)
    {
        $this->city = $city;
    }

    /**
     * Get city
     *
     * @return string 
     */
    public function getCity()
    {
        return $this->city;
    }

    /**
     * Set postCode
     *
     * @param string $postCode
     */
    public function setPostCode($postCode)
    {
        $this->postCode = $postCode;
    }

    /**
     * Get postCode
     *
     * @return string 
     */
    public function getPostCode()
    {
        return $this->postCode;
    }

    /**
     * Set country
     *
     * @param string $country
     */
    public function setCountry($country)
    {
        $this->country = $country;
    }

    /**
     * Get country
     *
     * @return string 
     */
    public function getCountry()
    {
        return $this->country;
    }

    /**
     * Set member
     *
     * @param Pomc\MembersBundle\Entity\Member $member
     */
    public function setMember(\Pomc\MembersBundle\Entity\Member $member)
    {
        $this->member = $member;
    }

    /**
     * Get member
     *
     * @return Pomc\MembersBundle\Entity\Member 
     */
    public function getMember()
    {
        return $this->member;
    }
}

Here is the memberform:

namespace Pomc\MembersBundle\Form\Type;

use \Symfony\Component\Form\AbstractType;
use \Symfony\Component\Form\FormBuilder;

class MemberType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder->add('firstName');
        $builder->add('lastName');
        $builder->add('address','collection', array( 'type' =>  new AddressType(),
                                              'allow_add' => true,
                                              'prototype' => true,
                                              'by_reference' => false,
                                              ));
    }

    public function getDefaultOptions(array $options)
    {
        return array('data_class' => 'Pomc\MembersBundle\Entity\Member');
    }
    /**
     * Returns the name of this type.
     *
     * @return string The name of this type
     */
    function getName()
    {
        return 'member';
    }


}

Here is the address form:

namespace Pomc\MembersBundle\Form\Type;

use \Symfony\Component\Form\AbstractType;
use \Symfony\Component\Form\FormBuilder;


class AddressType extends AbstractType
{
    public function buildForm(Formbuilder $builder, array $options)
    {
        $builder->add('firstLine');

    }

    public function getDefaultOptions(array $options)
    {
        return array('data_class' => 'Pomc\MembersBundle\Entity\Address');
    }
    /**
     * Returns the name of this type.
     *
     * @return string The name of this type
     */
    function getName()
    {
        return 'address';
    }

    function getIdentifier()
    {
        return 'address';
    }
}

Here is the controller:

namespace Pomc\MembersBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use \Pomc\MembersBundle\Entity\Member;
use \Symfony\Component\HttpFoundation\Request;
use \Pomc\MembersBundle\Form\Type\MemberType;

class DefaultController extends Controller
{

    public function indexAction($name)
    {
        return $this->render('PomcMembersBundle:Default:index.html.twig', array('name' => $name));
    }

    public function newAction(Request $request)
    {

        $member = new Member();

        $form = $this->get('form.factory')->create(new MemberType());

        if($request->getMethod() == 'POST')
        {
            $form->bindRequest($request);

            if($form->isValid())
            {
                $em = $this->getDoctrine()->getEntityManager();
                $em->persist($member);
                $em->flush();

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

    }
}

Here is the template:

<form action="{{ path('member_new') }}" method="post" {{ form_enctype(form)}}>
    {{ form_widget(form) }}
    <div>
    {{ form_row(form.address)}}
    </div>
    <input type="submit" />
</form>

Been a long time user of this site, but this is my first question.

Thank you

like image 223
Llewellyn Avatar asked Sep 21 '11 21:09

Llewellyn


1 Answers

Oh I faced the same problem, but I found the solution, hope this will help you :-)

You're forgetting to add an Address object to the member entity.

In your action you'll need to do the following:

$member = new Member();
$member->addAddress(new Address());

$form = $this->createForm(new MemberType(), $member);

And then in your template:

 {% for address in form.address %}
  {{ form_widget(address.firstLine) }}
 {% endfor %}

Btw your 'firstline' widget doesn't relate to an entity property.

Btw if you called addAddress two times, you would of course get two 'firstline' widgets in your form.

Hope this works. best of luck.

like image 107
Flukey Avatar answered Nov 14 '22 23:11

Flukey