Posted about 1 year ago by beberlei
Doctrine 2 supports composite keys of primitive types from the beginning, however we realized early that a very common use-case is a composite key with one or more elements being associated entities. For example think of a CMS System which allows Article Translations. A common SQL schema for this case would be:
CREATE TABLE article (id INT PRIMARY KEY,
title VARCHAR(255),
body LONGTEXT);
CREATE TABLE article_translations (article_id INT,
language CHAR(3),
title VARCHAR(255),
body LONGTEXT,
PRIMARY KEY (article_id,
language));
This sort of schema cannot be mapped with Doctrine 2 currently, it would be required to add another column id
on the article_translations table and enforce a unique constraint on article_id + language.
Under the umbrella of DDC-117 and some related tickets there were discussions about adding a feature that would help solve this problem: Allowing to add @Id to @ManyToOne or @OneToOne mappings. I committed this feature into an experimental Git branch today and we ask you to test this with as many crazy scenarios and use-cases as possible.
This feature can potentially be uber-powerful, however we want to be sure that it works correctly and does not have to many problematic edge-cases. Therefore we need your feedback.
git checkout DDC-117Personally I want this feature in core very much, however composite keys are very tricky. We want to find as many problematic cases with this feature as possible. That would enable us to evaluate if this approach will be merged into Doctrine 2.1 or not.
This feature currently only works with Annotations Mapping Driver. XML and YAML will follow later.
By the way, the previous example is actually one of the functional test-cases for this feature:
<?php /** * @Entity */ class DDC117Article { /** @Id @Column(type="integer") @GeneratedValue */ private $id; /** @Column */ private $title; /** * @OneToMany(targetEntity="DDC117Translation", mappedBy="article") */ private $translations; public function __construct($title) { $this->title = $title; $this->translations = new \Doctrine\Common\Collections\ArrayCollection(); } } /** * @Entity */ class DDC117Translation { /** * @Id @ManyToOne(targetEntity="DDC117Article") */ private $article; /** * @Id @column(type="string") */ private $language; /** * @column(type="string") */ private $title; public function __construct($article, $language, $title) { $this->article = $article; $this->language = $language; $this->title = $title; } } $article = new DDC117Article("foo"); $em->persist($article); $em->flush(); $translation = new DDC117Translation($article, "en", "Bar"); $em->persist($translation); $em->flush();
Comments (7) [ add comment ]
composite pk Posted by xplo about about 1 year ago.
Nice to see doctrine finally supporting composite pk (and i hope composite fk). This is one of the main reasons i never made any switch from propel.
nice job! Posted by mjh_ca about about 1 year ago.
This is great. Thanks for solving this critical shortcoming. Testing it now... !!
more one-to-many keys Posted by Bostjan about about 1 year ago.
It would be nice if I could have composite keys from 2 (or more) other entities.
Is it possible to do something as: advert( id (PK), ....) attribute( id (PK), ....) advert_attribute( advert_id (PK), attribute_id(PK), value, ..)
So i would have class advert { /** @Column @Id */ private $id
/* @OneToMany(targetEntity="advert_attribute", mappedBy="advert") */ private $values }
class attrbitue { /** @Column @Id */ private $id
/* @OneToMany(targetEntity="advert_attribute", mappedBy="attribute") */ private $values }
class advert_attribute { /** @Id @ManyToOne(targetEntity="advert") */ private $advert
/** @Id @ManyToOne(targetEntity="attribute") */ private $attribute }
@bostjan Posted by beberlei about about 1 year ago.
check the unit-tests this is supported
Posted by Posted by s9e about about 1 year ago.
That's a great news, I'm sure it'll save a lot of people a headache. I hope you'll be able to merge this feature into core soon.
@s9e Posted by BreizhReloaded about about 1 year ago.
You're right! I'm doing some tests to upgrade my projects on Doctrine 2.0, and that new feature is gonna save my life :)
Translatable behavior Posted by gediminas about about 1 year ago.
I have tried to implement the behavior using the event listener with more magic posibilities to simplify the reusable cases of translations needed and created a Translatable behavior which translates and loads the translations automatically depending on locale used: http://github.com/l3pp4rd/DoctrineExtensions