Friday, 23 August 2013

Doctrine 2.2/Symfony 2.2: Persisting an entity with a composite foreign key

Doctrine 2.2/Symfony 2.2: Persisting an entity with a composite foreign key

I must first establish that I'm a total newcomer to Doctrine, even though
I know enough about SQL and PHP/Symfony 2.
So, I created this IssueType entity associated to a SQL table:
/**
* IssueType
*
* @ORM\Table()
*
@ORM\Entity(repositoryClass="Blog\Bundle\CoreBundle\Entity\IssueTypeRepository")
*/
class IssueType
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
// Getters, setters...
}
I populated it, so the content of said table is now:
id | name
1 | Bande dessinée
2 | Livre
3 | Film
4 | Disque
Now I have this other entity, Role, which uses a composite key, made up of
a regular string (name) and a foreign key (id from IssueType):
/**
* Role
*
* @ORM\Table()
*
@ORM\Entity(repositoryClass="Blog\Bundle\CoreBundle\Entity\RoleRepository")
*/
class Role
{
/**
* @var IssueType
*
* @ORM\ManyToOne(targetEntity="Blog\Bundle\CoreBundle\Entity\IssueType")
* @ORM\JoinColumn(nullable=false)
* @ORM\Id
*/
private $issueType;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
* @ORM\JoinColumn(nullable=false)
* @ORM\Id
*/
private $name;
// Getters, setters...
}
Both tables are correctly generated by doctrine in the database. However,
although it should be trivial, I can't for the life of me find a single
example of a correct and successful persist operation in such a case.
What I try to do is the following:
$manager = $this->getDoctrine()->getManager();
$issueType = new IssueType();
$issueType->setId(1);
$role = new Role();
$role->setIssueType($issueType);
$role->setName('Dessinateur');
$manager->persist($role);
$manager->flush();
I thus try to persist the following:
Role: {
IssueType: {id: 1, name: ''},
name: 'Dessinateur',
}
And what I get is this nasty exception:
Entity of type Blog\Bundle\CoreBundle\Entity\Role has identity through a
foreign entity Blog\Bundle\CoreBundle\Entity\IssueType, however this
entity has no identity itself. You have to call EntityManager#persist() on
the related entity and make sure that an identifier was generated before
trying to persist 'Blog\Bundle\CoreBundle\Entity\Role'. In case of Post
Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL)
this means you have to call EntityManager#flush() between both persist
operations.
I understand it wants me to persist first the foreign entity, but I don't
want to do that, since the foreign issue type of ID#1 already exists in
the database and thus don't need persisting. How can it ask me that when I
did not specify any 'cascade' attribute in the annotations?
BTY I tried anyway to do as it says, and it expectedly ended up with a
duplicate entry error.
So, what should I do to make Doctrine understand that the foreign issue
type should not be persisted?

No comments:

Post a Comment