ManyToOne
Doctrine 2との関係を設定する方法を理解しようとして大きな時間を過ごしましたが、OneToMany
それでも機能しません...
アプリケーションの動作は次のとおりです。
- サイトに
Page
は - に
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());
}