0

ManyToOneDoctrine 2との関係を設定する方法を理解しようとして大きな時間を過ごしましたが、OneToManyそれでも機能しません...

アプリケーションの動作は次のとおりです。

  1. サイトにPage
  2. User書くことができCommentますPage

これが私のエンティティです(簡略化):

コメントエンティティ:

**
 * @ORM\Entity
 * @ORM\Table(name="comment")
 */
class Comment {
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
     protected $id;

    /**
     * Many Comments have One User
     *
     * @ORM\ManyToOne(targetEntity="\Acme\UserBundle\Entity\User", inversedBy="comments")
     */
    protected $user;

    /**
     * Many Comments have One Page
     *
     * @ORM\ManyToOne(targetEntity="\Acme\PageBundle\Entity\Page", inversedBy="comments")
     */
    protected $page;

    ...

    /**
     * Set user
     *
     * @param \Acme\UserBundle\Entity\User $user
     * @return Comment
     */
    public function setUser(\Acme\UserBundle\Entity\User $user)
    {
        $this->user = $user;
        return $this;
    }

    /**
     * Set page
     *
     * @param \Acme\PageBundle\Entity\Page $page
     * @return Comment
     */
    public function setPage(\Acme\PageBundle\Entity\Page $page)
    {
        $this->page = $page;
        return $this;
    }

ユーザーエンティティ:

/**
 * @ORM\Entity
 * @ORM\Table(name="fos_user")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * The User create the Comment so he's supposed to be the owner of this relationship
     * However, Doctrine doc says: "The many side of OneToMany/ManyToOne bidirectional relationships must be the owning
     * side", so Comment is the owner
     *
     * One User can write Many Comments
     *
     * @ORM\OneToMany(targetEntity="Acme\CommentBundle\Entity\Comment", mappedBy="user")
     */
    protected $comments;

    ...

    /**
     * Get Comments
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getComments() {
        return $this->comments ?: $this->comments = new ArrayCollection();
    } 

ページエンティティ:

/**
 * @ORM\Entity
 * @ORM\Table(name="page")
 */
class Page
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * One Page can have Many Comments
     * Owner is Comment
     *
     * @ORM\OneToMany(targetEntity="\Acme\CommentBundle\Entity\Comment", mappedBy="page")
     */
    protected $comments;

    ...

    /**
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getComments(){
        return $this->comments ?: $this->comments = new ArrayCollection();
    }

Comment双方向の関係で、PageまたはからUser(を使用して)のコレクションを取得できるようにする必要がありgetComments()ます。

私の問題は、新しいものを保存しようとすると、DoctrineがエンティティCommentを作成できないというエラーが表示されることです。Pageこれは、(ただし、そうする必要がありますが)見つからないために発生していると思います。そのPageため、新しいPageエンティティを作成して、後で作成しようとしているエンティティにリンクCommentしようとしています。

これが私のコントローラーからのメソッドですComment

public function createAction()
    {
        $user = $this->getUser();
        $page = $this->getPage();

        $comment = new EntityComment();
        $form = $this->createForm(new CommentType(), $comment);

        if ($this->getRequest()->getMethod() === 'POST') {
            $form->bind($this->getRequest());
            if ($form->isValid()) {
                $em = $this->getDoctrine()->getManager();

                $comment->setPage($page);
                $comment->setUser($user);

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

                return $this->redirect($this->generateUrl('acme_comment_listing'));
            }
        }

        return $this->render('AcmeCommentBundle:Default:create.html.twig', array(
            'form' => $form->createView()
        ));
    }

なぜこれが起こっているのか分かりません。Pageこのコントローラーでオブジェクトをチェックしました($this->getPage()セッションに保存されたオブジェクトを返す--によって返されます)。これは、存在する有効なPageエンティティです(DBもチェックインしました)。

私は今何をすべきかわからないし、同じ問題を抱えている人を見つけることができません:(

これは私が持っている正確なエラーメッセージです:

エンティティの永続化操作をカスケードするように構成されていない関係'Acme\ CommentBundle \ Entity \ Comment#page'を通じて、新しいエンティティが見つかりました:Acme \ PageBundle \ Entity \ Page@000000005d8a1f2000000000753399d4。この問題を解決するには:この不明なエンティティでEntityManager#persist()を明示的に呼び出すか、カスケードを構成して、この関連付けをマッピングに永続化します(例:@ ManyToOne(..、cascade = {"persist"}))。問題の原因となっているエンティティがわからない場合は、「Acme \ PageBundle \ Entity \ Page#__ toString()」を実装して手がかりを取得してください。

ただし、カスケードでページを作成したくないので追加したくcascade={"persist"}ありませんが、既存のページをリンクするだけです。

UPDATE1:

設定する前にページをフェッチすると、機能しています。しかし、なぜそうすべきなのかはまだわかりません。

public function createAction()
        {
            $user = $this->getUser();
            $page = $this->getPage();

            // Fetch the page from the repository
            $page = $this->getDoctrine()->getRepository('AcmePageBundle:page')->findOneBy(array(
               'id' => $page->getId()
            ));

            $comment = new EntityComment();

            // Set the relation ManyToOne
            $comment->setPage($page);
            $comment->setUser($user);

            $form = $this->createForm(new CommentType(), $comment);

            if ($this->getRequest()->getMethod() === 'POST') {
                $form->bind($this->getRequest());
                if ($form->isValid()) {
                    $em = $this->getDoctrine()->getManager();

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

                    return $this->redirect($this->generateUrl('acme_comment_listing'));
                }
            }

            return $this->render('AcmeCommentBundle:Default:create.html.twig', array(
                'form' => $form->createView()
            ));
        }

UPDATE2:

結局、(完全なオブジェクトではなく)セッションにpage_idを格納することになりました。これは、格納するための使用セッションがなく、IDだけが存在するという事実を考慮すると、より良い考えだと思います。Pageまた、エンティティを取得するときにDoctrineがクエリをキャッシュすることを期待しています。

Pageしかし、誰かが私がセッションからエンティティを使用できなかった理由を説明できますか?これが私がセッションを設定した方法です:

$pages = $site->getPages(); // return doctrine collection
if (!$pages->isEmpty()) {         
    // Set the first page of the collection in session
    $session = $request->getSession();
    $session->set('page', $pages->first());
}
4

1 に答える 1

0

実際、Pageオブジェクトはエンティティマネージャに認識されておらず、オブジェクトはセッションから取得されます。(正しい用語は、エンティティマネージャーから「切り離された」ものです。)そのため、新しい用語を作成しようとします。

別のソースからオブジェクトを取得する場合は、merge関数を使用する必要があります。(セッションから、シリアル化解除関数からなど...)

それ以外の

// Fetch the page from the repository
            $page = $this->getDoctrine()->getRepository('AcmePageBundle:page')->findOneBy(array(
               'id' => $page->getId()
            ));

あなたは単に使用することができます:

$page = $em->merge($page);

セッションでオブジェクトを操作する場合に役立ちます。

エンティティのマージの詳細については、こちらをご覧ください

于 2013-02-13T09:04:24.820 に答える