Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two Generated Values in Doctrine

i would like to implement a human-readable ID in my Doctrine-Entity. I want to keep the DB-ID for working and adding something like "PRE12-00005" (with Prefix and Year, and start at 0 every new year). I tried to add a Custom-ID-Generator, but it seems that Doctrine can't work with two generated Values in one Entity.

/**
 * @var integer
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
protected $id;

/**
 * @var string
 * @ORM\Column(name="name", type="string", length=25, unique=true)
 * @ORM\GeneratedValue(strategy="CUSTOM")
 * @ORM\CustomIdGenerator(class="NameGenerator")
 */
protected $name;

Doctrine always try to save the return value from my generator into the "id"-Field and null into "name". Is there another way to implement it?

like image 922
icksde Avatar asked Dec 17 '12 14:12

icksde


1 Answers

From what I know the GeneratedValue strategy is reserved for the primary key, meaning you can only use it once per Entity.

Depending on your needs you have a few options though:

  • You can always have a prePersist lifecycle event, setting any value you like for the name before you persist it the first time.

  • If you depend on the id to generate another unique id from it, you could implement a postPersist event, set your name there and make sure you flush twice (The first time to generate the primary key, the second time to save the name).

  • If it's ok for you that the name is empty in the database for some time, it could be ok to implement a postLoad event, which fills the name if it's empty. This way your application always sees the name (because it's either loaded from the database or filled by the postLoad event) and when you add or edit information the first time after the initial save, your name will also be saved

  • It could be ok to not save the name and have it generated by some cronjob/deamon/queue so your application does not have to deal with it. The only thing you would need to do is make sure a missing name does not screw up something.

  • Maybe it might be ok to generate a key which does not depend on the primary key and thus can be generated by an global event handler. You of course have the drawback that such an event handler, because he is global, gets called for every object you persist, no matter if it's the correct entity.

  • Last, but not least, it might be ok to fallback to Stored Procedures/Triggers to let the database handle this. This way you don't have to mess with this inside your application. But beware, there might be pitfalls on the way (like a developer forgetting about this because it's not in the code but in the database!).

There may be other ways. What I was trying to say is: Don't use generatedValue for non-primary key properties!

like image 100
Sgoettschkes Avatar answered Oct 09 '22 13:10

Sgoettschkes