【问题标题】:Save related Object Symfony 2保存相关对象 Symfony 2
【发布时间】:2015-02-15 05:26:40
【问题描述】:

我有用户和帖子。一对多

//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;

控制器

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

我必须使用 setPosts 来持久化相关用户吗?我可以用级联或类似的东西保存吗?

我知道

Doctrine 中有两种级联:

1) ORM 级别

2) 数据库级

但是我不明白什么时候用cascade={"persist"})

我的问题是:

  • 如何保存帖子对象中的用户相关信息?
  • 何时以及为何使用 cascade={"persist"})?

更新

我试过了

//用户

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

控制器

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

但不起作用,数据库中的字段user_id为空

【问题讨论】:

标签: php symfony


【解决方案1】:

您的实体应如下所示:

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
    }
}

在这种情况下,如果您同时创建用户及其帖子,则可以使用cascade:您希望同时保留用户和帖子,并将帖子附加到用户。

如果用户在您持久化帖子时已经存在,您只需设置帖子的作者并持久化后者:

Controller.php

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

顺便说一句,在一对多关系中,拥有方是多方,在这种情况下是 Post。

【讨论】:

  • inversedBy 为拥有方。据此:doctrine-orm.readthedocs.org/en/latest/reference/…
  • @monkeyUser cascade 可能在关系的两边,这取决于您要实现的目标。在您给$post->setPosts($this->getUser()); 的代码中,为什么要将User 传递给setPosts 方法?通常,您希望在嵌入表单时使用级联,例如,如果您将标签实体附加到您的帖子,您可能希望在持久化帖子时执行级联持久化,因此标签也会被持久化。
  • @OIS 正是如此,所以多方拥有该关系,因为它将拥有数据库中的外键。不过,引用 Doctrine 的文档 ManyToOne is always the owning side of a bidirectional association.
  • @paulgv 感谢您的回复,然后为了将我的 user_id 保存在 Post Table 中,我不必使用级联,但我可以做 $post->setPosts($this->getUser()); 然后坚持 Post。否则如何在 Post 表中保存 user_id?
  • 是的,如果您要以相同的形式创建用户和帖子,则需要使用级联,因为您需要先持久化用户,然后再持久化帖子,与新持久的用户作为他们的作者。
【解决方案2】:
/**
 * @ORM\OneToMany(targetEntity="Post", mappedBy="posts", cascade={"persist"})
 */
private $posts;

所以$em->persist($user); 所做的只是告诉实体管理器它应该管理 $user。被管理的实体只是意味着当您调用 $em->flush() 时,它会将该实体以其当前状态保存到数据库中,方法是在所有需要的表中创建新行,或者更新现有表。

所以要真正回答你的问题。 通过将 cascade={"persist"} 添加到此注解中,实体管理器知道如果正在管理此 User 对象,则在进行刷新调用时,它还需要执行您为所有 Post 对象定义的任何级联操作与该用户关联,并将他们的更改(或根据需要创建新行)保存到数据库中(或删除,如果您有级联删除并从该用户的帖子集中删除帖子)。

【讨论】:

  • 但在我的情况下,我必须使用$post->setPosts($this->getUser());保存相关用户
  • 如果我尝试您的解决方案并添加 $user->addPost($post); $em->persist($user) 我有此错误 User#posts' that is not configured to cascade persist
猜你喜欢
  • 2020-09-03
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 2012-06-16
  • 1970-01-01
  • 2019-05-20
  • 2017-04-12
  • 2011-09-11
相关资源
最近更新 更多