RydelHouse
RydelHouse

Reputation: 362

Embed a collection of forms - doctrine, symfony

I have two tables "RFQ" and "RFQitem". I can make form which can create RFQ with their title description and amount. And I can create RFQitem form which can create RFQitem with their title, description and amount.

Problems starts when I need to upgrade my RFQ form, so that I can make in it RFQitems which will saves in their table, but it need to be assigned to RFQ.

In symfony documentation is great example which actually works for me, but this is example is with task and their tags. So task there is with more than one attributes (name, description), but tags are only with one - name.

My RFQ entity with RFQItems looks like this:

    /**
 * @ORM\ManyToMany(targetEntity="RFQItem", cascade={"persist"})
 * @ORM\JoinTable(name="rfq_item_title",
 *      joinColumns={@ORM\JoinColumn(name="rfq_item_title", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="id", referencedColumnName="id")}
 * )
 */
protected $rfq_item_title;

/**
 * @ORM\ManyToMany(targetEntity="RFQItem", cascade={"persist"})
 * @ORM\JoinTable(name="rfq_item_description",
 *      joinColumns={@ORM\JoinColumn(name="rfq_item_description", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="id", referencedColumnName="id")}
 * )
 */
protected $rfq_item_description;

/**
 * @ORM\ManyToMany(targetEntity="RFQItem", cascade={"persist"})
 * @ORM\JoinTable(name="rfq_item_amount",
 *      joinColumns={@ORM\JoinColumn(name="rfq_item_description", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="id", referencedColumnName="id")}
 * )
 */
protected $rfq_item_amount;

But I know that this is wrong, but how I make ManyToMany relation with RFQitem which have more than one attributes?

Upvotes: 0

Views: 375

Answers (1)

Martin Fasani
Martin Fasani

Reputation: 823

The best way to go is to have this two entities as you are actually doing, the father and the collection childs with the attributtes you like, but do not get fixated to the Symfony example. It's a theoretical OOP, has not relations defined, so I'm going to make my best try to paste a coherent example based on a Theater->Works collection:

class Theater
{
private $name;
private $id;

/**
 * Set name
 * @param string $name
 * @return Theater
 */
public function setName($name)
{
    $this->name = $name;
    return $this;
}

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

/**
 * Get id
 * @return integer 
 */
public function getId()
{
    return $this->id;
}
/**
 * @var \Doctrine\Common\Collections\Collection
 */
private $work;

/**
 * Constructor
 */
public function __construct()
{
    $this->work = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add work
 *
 * @param \Acme\RelationBundle\Entity\Work $work
 * @return Theater
 */
public function addWork(\Acme\RelationBundle\Entity\Work $work)
{
    $this->work[] = $work;
    return $this;
}

/**
 * Remove work
 * @param \Acme\RelationBundle\Entity\Work $work
 */
public function removeWork(\Acme\RelationBundle\Entity\Work $work)
{
    $this->work->removeElement($work);
}

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

Then the child entity Work:

class Work
{
// took out some comments to make it shorter
private $name;
private $description;
private $id;


/**
 * Set name
 * @param string $name
 * @return Work
 */
public function setName($name)
{
    $this->name = $name;
    return $this;
}

/**
 * Set description :  And any others setters/getters with the attributes you want
 * @param string $description
 * @return Work
 */
public function setDescription($description)
{
    $this->description = $description;

    return $this;
}

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

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

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


public function __toString()
{
    return (string) $this->getName();
}
}

The trick is to use this Collection in Doctrine and then make a two Form Types, the parent and the childs, something like this example below.

TheatherType Formtype includes the Work childs:

          $buider->add('rowswork', 'collection', array(
                'type' => new WorkChildType(),
                'allow_add' => true,
                'allow_delete' => true,
            )
        );

So there is one row with their Work childs that have their own WorkChildType with the attributes from the entity. It's like a form, with an embedded array collection of items, in your case an "RFQ" father form and "RFQitem" childs.

Upvotes: 1

Related Questions