monkeyUser
monkeyUser

Reputation: 4679

Save related Object Symfony 2

I have User and Posts. One To Many

//user.php

 /**
 * @ORM\OneToMany(targetEntity="Post", mappedBy="posts")
 */
private $posts;

public function __construct () {
    $this->posts = new ArrayCollection();
}

post.php

/**
 * @ORM\ManyToOne(targetEntity="User", inversedBy="posts")
 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")

 */
private $posts;

controller

$post->setPosts($this->getUser());
$em->persist($post);
$em->flush();

I have to use setPosts for persist related user? Can I save with cascade or something of this?

I know that

There are two kinds of cascades in Doctrine:

1) ORM level

2) Database level

But I don't understand when use cascade={"persist"})

My questions are:

update

I tried

//user

/**
 * @ORM\OneToMany(targetEntity="Post", mappedBy="posts",cascade={"persist"})
 */
private $posts;

controller

 $user = $this->getUser();
 $user->addPost($post);
 $em->persist($user);
 $em->flush();

But doesn't works, the field user_id in database is empty

Upvotes: 0

Views: 2763

Answers (2)

paulgv
paulgv

Reputation: 1828

Your entities should look like this :

User.php

class User {
    /**
     * @ORM\OneToMany(targetEntity="Post", mappedBy="user", cascade={"persist"})
     */
    private $posts;

    public function addPost(Post $post) {
        $post->setUser($this); // Call Post's setter here
        $this->$posts[] = $post; // Add post to the collection
    }
}

Post.php

class Post {
    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="posts")
     */
    private $user;

    public function setUser(User $user) {
        $this->user = $user; // Set post's author
    }
}

In that case, you could use cascade if you are creating the user and its posts at the same time : you want to persist both the user and the posts, and attach the posts to the user.

If the user already exists at time you're persisting the post, you just have to set the post's author and persist the latter :

Controller.php

public function editPostAction() {
    // ...
    $post->setUser($this->getUser());
    $em->persist($post);
    $em->flush();
    // ...
}

By the way, in a One-To-Many relation, the owning side is the Many side, Post in this case.

Upvotes: 3

echochamber
echochamber

Reputation: 1815

/**
 * @ORM\OneToMany(targetEntity="Post", mappedBy="posts", cascade={"persist"})
 */
private $posts;

So all $em->persist($user); does is tell the entity manager that it should be managing $user. An entity being managed just means that when you call $em->flush() it will save that entity in its current state to the database, either by creating a new row in all the tables required, or updating the existing ones.

So to actually answer your question. By adding the cascade={"persist"} to this annotation, the entity manager knows that if this User object is being managed, when a flush call is made, it will also need to perform whatever cascade operations you have defined for all Post objects associated with this User, and save their changes (or create new rows as required) to the database (or delete if you have cascade delete and remove a post from this user's post collection).

Upvotes: 0

Related Questions