[DDC-2200] Duplicates returned while accessing associations from @PostPersist callback Created: 15/Dec/12  Updated: 15/Dec/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.1
Fix Version/s: None
Security Level: All

Type: Bug Priority: Minor
Reporter: Brent Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
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


Generated at Wed Apr 23 08:09:20 UTC 2014 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.