22

Is there any way to get an entity ID before the persist/flush? I mean:

$entity = new PointData();
$form   = $this->createForm(new PointDataType(), $entity);

If I try $entity->getId() at this point, it returns nothing.

I can get it working by:

$em->persist($entity);
$em->flush();

(supposing $em = $this->getDoctrine()->getEntityManager();)

How can I achieve this?

2
  • Read about identifier generation strategies on Doctrine's documentation pages. Commented May 7, 2012 at 16:39
  • Thank you Crozin. I had already read all that stuff. I´m not trying to get the next auto index. It would fail if 2 users called that action simultaneously. Commented May 7, 2012 at 16:42

5 Answers 5

35

If you want to know the ID of an entity before it's been persisted to the database, then you obviously can't use generated identifiers. You'll need to find some way to generate unique identifiers yourself (perhaps some kind of hash function can produce unique-enough values).

This is rarely a good idea, though, so you should be careful.

I would think very carefully about why I need to know the identifier before flush. Doctrine is quite good at letting you build up a big object graph, and persist/flush it all at once. It seems likely that you've got something ugly in your architecture that you're trying to work around. It might be a good idea to review that before going down the application-generated-id route.

Sign up to request clarification or add additional context in comments.

3 Comments

Maybe you could use UUID for this task, since they are practically unique (en.wikipedia.org/wiki/Universally_unique_identifier) and they can be generated in advance, from PHP for example. I don't like them much, but would be a good solution.
@JorgeeFG - Absolutely. UUIDs are a great for this use-case. In the years since I wrote this answer, I've started preferring UUIDs as identifiers for entities. github.com/ramsey/uuid is a pretty solid library for generating them, and github.com/ramsey/uuid-doctrine provides a doctrine type implementation that works well.
In fact, Ocramius himself (the Doctrine ORM project leader) recommends generating our own UUIDs instead of relying on Doctrine for that… One of the reasons for that is that this way we can have valid entities from the moment they're instantiated, also we know which ID they will have before persisting them...
12

You can use the @PostPersist annotation. A method annotated with it will be executed just before the flush ends and the entity Id is already available.

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/events.html

postPersist - The postPersist event occurs for an entity after the entity has been made persistent. It will be invoked after the database insert operations. Generated primary key values are available in the postPersist event.

<?php

use Doctrine\ORM\Mapping as ORM;

/** 
 * @ORM\Entity 
 * @ORM\HasLifecycleCallbacks 
 */
class PointData
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
     private $id;

     ...

     /** 
      * @ORM\PostPersist 
      */
     public function onPostPersist()
     {
         // Put some simple logic here that required the auto-generated Id.

         $this->doSomething($this->id);
     }
    
     ...

}

2 Comments

It'd probably be better to use an event listener if you're using Symfony but still +1
I prefer to annotate the entity so that logic is not hidden in another place.
2

Not sure why you need the ID before flushing, but, if you really need to persist the entity without saving to the database you can try using Transactions.

Try something like this:

$em->beginTransaction();
$em->persist($entity);
$em->flush();
$id = $entity->getId();
//do some stuff and save when ready
$em->commit();

Comments

0

you can use an auto generate ID to get a key like universally unique identifiers (UUID) or you can take the events of symfony: postFlush - The postFlush event occurs at the end of a flush operation.

Comments

-2
$em = $this->getDoctrine()->getManager();
$entity = new PointData();

$em->persist($entity);

$entity->getId() <-- return <int>

$em->flush();

after persist you can get id

1 Comment

Welcome to StackOverflow. It's good to provide code snippet as solutions, but code-only answers are considered bad practice. Please elaborate what this snippet does and how it fixes the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.