Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-2200

Duplicates returned while accessing associations from @PostPersist callback

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 2.3.1
    • Fix Version/s: None
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None

      Description

      When creating a new Post and adding it to a collection in an existing Thread (i.e. loaded from the database), referencing Thread's posts collection in Post's @PostPersist callback returns the Post twice. To clarify, this only happens when Thread was previously persisted. If I'm creating a new Thread object the code works as expected. I've included some sample code to better illustrate my issue.

      I don't know if this is a bug, or if I'm doing something that I shouldn't be, but I couldn't find this limitation mentioned in the documentation, and this seems to go against the expected behavior.

      Here are my sample entities:

      
      /**
       * @Entity
       * @Table(name="thread")
       */
      class Thread
      {
          /** 
           * @Id
           * @GeneratedValue
           * @Column(type="integer")
           */
          protected $id;
      
          /** 
           * @OneToMany(targetEntity="Post", mappedBy="thread", cascade={"persist", "remove"})
           */
          protected $posts;
      
          public function __construct() {
              $this->posts = new ArrayCollection();
          }   
      
          public function getPosts() {
              return $this->posts->toArray();
          }   
      
          public function addPost(Post $post) {
              $post->setThread($this);
              $this->posts->add($post);
          }   
      }
      
      /**
       * @Entity
       * @Table(name="post")
       * @HasLifecycleCallbacks
       */
      class Post
      {
          /** 
           * @Id
           * @GeneratedValue
           * @Column(type="integer")
           */
          protected $id;
      
          /** 
           * @ManyToOne(targetEntity="Thread", inversedBy="posts")
           * @JoinColumn(name="thread_id", referencedColumnName="id")
           */
          protected $thread;
      
          public function getId() {
              return $this->id;
          }   
      
          /** 
           * @PostPersist
           */
          public function onPostPersist() {
              $posts = $this->thread->getPosts();
              foreach ($posts as $post) {
                  echo 'id: ' . $post->getId() . ' type: ' . get_class($alert) . '<br />';
              }   
          }
      
          public function setThread(Thread $thread) {
              $this->thread = $thread;
          }   
      }
      
      

      And the calling code:

      
      // Grab an existing thread.
      $thread = $em->getReference('Thread', 1); 
      $thread->addPost(new Post());
      $em->flush();
      
      

      This outputs:

      
      id: 1 type: Post
      id: 1 type: Post
      
      

      Alternatively:

      
      // Create a new thread.
      $thread = new Thread()
      $thread->addPost(new Post());
      $em->persist($thread);
      $em->flush();
      
      

      This outputs:

      
      id: 1 type: Post
      
      

        Activity

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Brent
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: