n00n
n00n

Reputation: 664

ZF2 / Doctrine wont let me save a collection

Got to handle an entity, called Collection, which has an array to be saved as a different entity.

This is what I use in the controller, to test my entities:

// setup items in a controller
$i1 = new Item();
$i1->setInfo('test2');
$i2 = new Item();
$i2->setInfo('example');

// create the collection
$pc = new Collection();
$pc->setId(1);
// set some vars / members
$pc->setInfo('test123');
$pc->setOwner(1);
$pc->setGroup(1);
$pc->setConfig(1);

// add the items
$pc->add($pi1);
$pc->add($pi2);

// store everything
$em = $this->getEntityManager();
$em->persist($pc);
$em->flush();

This is my Item entity:

<?php

/**
 * Item
 * @package application\Entity
 *
 * @ORM\Entity
 * @ORM\Table(name="items")
 */
class Item
{
    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     * @ORM\Column(name="info", type="text")
     */
    protected $info;

    /**
     * @var
     * @ORM\ManyToOne(targetEntity="Collection", inversedBy="items")
     * @ORM\JoinColumn(name="cid", referencedColumnName="id")
     */
    protected $collection;
    protected $collection;

    /**
     * @return string
     */
    public function getInfo()
    {
        return $this->info;
    }

    /**
     * @param string $info
     */
    public function setInfo($info)
    {
        $this->info = $info;
    }

}

This is the code in the collection entity

/**
 * Collection
 * @package Application\Entity
 *
 * @ORM\Entity
 * @ORM\Table(name="collections")
 */
class Collection
{
    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(name="usr", type="integer")
     */
    protected $owner;
    /**
     * @var string
     *
     * @ORM\Column(name="grp", type="integer")
     */
    protected $group;

    /**
     * @var string
     *
     * @ORM\Column(name="cnf", type="integer")
     */
    protected $config;

    /**
     * @var string
     *
     * @ORM\Column(name="info", type="text")
     */
    protected $info;

    /**
     * @var
     * @ORM\OneToMany(targetEntity="Item", mappedBy="items", cascade="all")
     */
    protected $items;

    public function __construct(){
        $this->items = new ArrayCollection();
    }

    public function add(Item $oItem){
        $this->items->add($oItem);
    }

I would expect it to create items which have the id of the Collection in their column 'cid'. But this column is always null:

And another problem, it always saves a new Collection. I expected that setting the id would override the original.

Upvotes: 2

Views: 51

Answers (1)

edigu
edigu

Reputation: 10099

I strongly recommend reading several times to fully understand the differences between owning-side and inverse-side before playing with bi-directional associations.

The Item entity is owning-side in this scenario (from doctrine's perspective) (1). You're persisting the inverse-side (2). Doctrine will only check the owning side of an association for changes (3). Also some setters & getters are missing in your entities which required to build a correct bidirectional relationship (4).

Add this methods to Item entity:

public function setCollection(Collection $col = null)
{
    $this->collection = $col;
    return $this;
}

public function getCollection()
{
    return $this->collection;
}

And change the add method in Collection entity something like this:

public function add(Item $oItem)
{
    $this->items->add($oItem);
    $oItem->setCollection($this); // Notice this line
}

When you want to remove an Item from a Collection;

public function removeItem(Item $oItem)
{
    $this->items->removeElement($oItem);
    $oItem->setCollection(null); // This is important too
}

You may also want to read about transitive persistence section of the documentation before using cascade="all" strategy.

Hope it helps.

Upvotes: 2

Related Questions