Doctrine2 ORM OneToOne不工作UPDATE更改为ManyToMany但不完全正常工作 [英] Doctrine2 ORM OneToOne not working UPDATE changed to ManyToMany but not fully working

查看:97
本文介绍了Doctrine2 ORM OneToOne不工作UPDATE更改为ManyToMany但不完全正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个表格,称为广告和用户。用户ID被写入广告表。我现在创建了一个名为书签的第三个表。该表有2列,advert_id和user_id。当我看到我喜欢的广告时,我可以添加一个书签,以便我的私人部分更容易找到它。当我在我的私人部门看到我的书签时,我想立即看到广告内容,所以在我的存储库中,我想创建一个加入来阅读广告表中的信息。我以为这将是一个OneToOne关系。我还必须确保,如果广告被删除,那么所有的书签都需要被删除,所以我认为它是双向的关系。所以我有以下:



Entity / Bookmark.php

 $ $ $ $ $ 

$ b * @ ORM\Table(name =bookmark)
* @ ORM\Entity(repositoryClass = ads\Repository\BookmarkRepository)
* /
class书签
{
/ **
* @var整数
* @ ORM\\ \\ id
* @ ORM\Column(name =advert_id,type =integer,nullable = false)
* @ ORM\OneToOne(targetEntity =Advert,mappedBy =bookmark )
* @ ORM\JoinColumn(name =advert_id,referencedColumnName =id)
* /
private $ advertId;

/ **
* @var整数
* @ ORM\Id
* @ ORM\Column(name =user_id,type =integer ,nullable = false)
* @ ORM\OneToOne(targetEntity =User)
* @ ORM\JoinColumn(name =user_id,referencedColumnName =id)
* /
private $ userId;


public function setAdvertId($ advertId)
{
$ this-> advertId = $ advertId;
return $ this;
}


public function getAdvertId()
{
return $ this-> advertId;
}


public function setUserId($ userId)
{
$ this-> userId = $ userId;
return $ this;
}


public function getUserId()
{
return $ this-> userId;
}

Entity\Advert.php

  / **广告
*
* @ ORM\Table(name =advert)
* @ ORM\Entity(repositoryClass =Advert \ Repository\AdvertRepository)
* /

类别广告
{
/ **
* @var integer
*
* @ ORM\Column(name =id,type =integer,nullable = false)
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =IDENTITY)
* /
private $ id;

/ **
* @ ORM\OneToOne(targetEntity =书签,inversedBy =advert)
* @ ORM\JoinColumn(name =id ,referencedColumnName =advert_id)
** /
private $ bookmark;

public function setBookmark($ bookmark)
{
$ this-> bookmark = $ bookmark;
return $ this;
}


public function getBookmark()
{
return $ this->书签;
}



public function addBookmark($ bookmark)
{
$ this-> bookmark-> add($ bookmark );
}


public function removeBookmark($ bookmark)
{
$ this-> bookmark-> removeElement($ bookmark);
}

Advert \Repository\Advert\Repository.php

  class BookmarkRepository extends EntityRepository 
{
public function getBookmarksByUserIds($ userId)
{
$ query = $ this-> _em-> getRepository($ this-> getEntityName()) - > createQueryBuilder('b')
- > join('广告ID','a')
- > andWhere('a.userId =:userid')
- > setParameter('userid',$ userId)
;
return $ query-> getQuery() - > getResult();
}

我做错了什么或我的错误在哪里?我收到错误消息:



广告\Entity\Bookmark没有关联名称advertId



正如我所说,当我点击将广告添加到书签时,表书签只会被填充。当我点击显示我的书签,如果广告或用户被删除,我需要加入才能显示广告内容,所有书签都需要从书签表中删除。这是一个OneToOne双向关系,有什么问题吗?



更新1以下不工作



我已经更新了以下2个文件,但我没有显示任何书签。相反,我应该看到收藏的广告列表和广告的详细信息。我甚至还没有尝试让我的服务书签广告或方法来检查一个广告是否被加书签。我以前有工作,但我想我现在真的很困惑。



AdvertController.php

  public function watchlistAction()
{
$ user_id = $ this-> zfcUserAuthentication() - > getIdentity() - > getId();
$ adverts = $ this-> getEntityManager() - > getRepository('Advert'\\Entity\User') - > findBookmarksByUserId($ user_id);
返回新的ViewModel(数组(
'adverts'=> $ adverts,
));
}

Repository\UserRepository.php

 类UserRepository扩展EntityRepository 
{

public function findBookmarksByUserId($ userId)
{
$ query = $ this-> _em-> getRepository($ this-> getEntityName()) - > createQueryBuilder('b')
- > join('b.bookmarks' ,'a')
- > join('b.adverts','c')
- > andWhere('a.user =:userid')
- > setParameter ('userid',$ userId)
;
return $ query-> getQuery() - > getResult();
}

更新2下方工作



你是对的,我不需要UserRepository查询查看已收藏的广告列表。我只需要更改



AdvertController.php

 code> public function watchlistAction()
{
$ user_id = $ this-> zfcUserAuthentication() - > getIdentity() - > getId();
//通过引用获取用户(没有查询执行)
$ user = $ this-> getEntityManager() - > getReference('Advert'\\Entity\User',$ user_id);
$ adverts = $ user-> getBookmarks();

返回新的ViewModel(array(
'adverts'=> $ adverts,
));
}

好消息,在我删除广告的那一刻,书签自动在书签数据库表中删除。现在我只需要找出如何添加书签,所以我必须改变我的服务。一旦我得到这个工作,我会更新这个职位供别人看。



更新3以下不工作



不幸的是我没有得到以下3我的服务方法工作。我显然必须选择1条记录,要么检查状态(已经和否已经签名),删除书签(由adsId定义)或添加书签(由adsId定义)



公共函数checkAdvertBookmarkStatus($ advertId)
{
$ userId = $ this-> getUserEntity() - > getId();
//通过引用获取用户(没有查询执行)
$ user = $ this-> getEntityManager() - > getReference('Advert'\\Entity\User',$ userId);

$ bookmarkStatus = $ this-> getEntityManager() - > getRepository('Advert'\\Entity\User')
- > findOneBy(array('advert'=> ; $ advertId,'userId'=> $ userId));

return $ bookmarkStatus;
}

public function saveAdvertBookmark($ advertId)
{
$ bookmark = new UserEntity();
$ userId = $ this-> getUserEntity() - > getId();

// $ bookmark-> addBookmark($ advertId);
$ bookmark-> setAdvertId($ advertId);
$ bookmark-> setUserId($ userId);

#将新书签写入数据库tbl书签
$ this-> getEntityManager() - > persist($ bookmark);
$ this-> getEntityManager() - > flush();
}


public function removeAdvertBookmark($ advertId)
{
$ bookmark = new UserEntity();
$ userId = $ this-> getUserEntity() - > getId();
$ bookmark = $ this-> getEntityManager() - > getRepository('Advert \Entity\Bookmark')
- > findOneBy(array('advertId'=> $ advertId, 'userId'=> $ userId));

#从tbl书签中删除bookmmark
$ this-> getEntityManager() - > remove($ bookmark);
$ this-> getEntityManager() - > flush();

}

我想答案在教程中,我保留阅读,但我完全不明白。当我使用BookmarkEntity时,我可以添加书签,但我不知道如何通过UserEntity

解决方案

p> OneToOne关系在这里是错误的选择,这意味着用户只能为一个广告添加书签,并且广告只能由一个用户加入书签。因为用户应该能够将许多广告加入书签,并且广告应该被许多用户加入书签,所以您需要一个ManyToMany关系。



您的想法是创建一个映射表书签如果您使用数据库,则不会出错。但是,您不需要在Doctrine中将其创建为实体。您可以简单地将广告添加到用户名为书签的关联中,以显示已加书签的广告,反之亦然:



用户实体

  / ** 
* @var整数
*
* @ ORM\Column(name = id,type =integer,nullable = false)
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =IDENTITY)
* /
私人$ id;

/ **
* @ ORM\ManyToMany(targetEntity =Application\Entity\Advert,inversedBy =bookmarks,cascade = {persist})
* @ ORM\JoinTable(name =bookmarks,
* joinColumns = {@ ORM\JoinColumn(name =user_id,referencedColumnName =id)},
* inverseJoinColumns = {@ ORM\JoinColumn(name =advert_id,referencedColumnName =id)}
*)
* /
private $ bookmarks;

广告实体

  / ** 
* @var整数
*
* @ ORM\Column(name =id,type =integer ,nullable = false)
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =IDENTITY)
* /
private $ id;

/ **
* @ ORM\ManyToMany(targetEntity =Application\Entity\User,mappedBy =bookmarks,cascade = {persist})
* @ ORM\JoinTable(name =bookmarks,
* joinColumns = {@ ORM\JoinColumn(name =advert_id,referencedColumnName =id)},
* inverseJoinColumns = {@ ORM\JoinColumn(name =user_id,referencedColumnName =id)}
*)
* /
private $ bookmarks;

您可能还想阅读这篇文章:
http://doctrine-orm.readthedocs.org/en/latest/reference/working- with-associations.html



编辑:如何添加和删除书签



原则中的关联与领域完全不同,尽管这两者都是您的实体中的属性。要处理书签,您可以直接在用户实体中添加或删除广告实体。例如:

  $ bookmarks = $ user-> getBookmarks(); 
$ bookmarks [] = $ advert;

这将为用户添加一个书签,并将在持续 flush 。为了使这更容易,您可以定义删除器加法器



使用语句:

 使用Doctrine\Common\Collections\ArrayCollection; 
使用Doctrine\Common\Collections\Collection;

代码:

  / ** 
* @param Collection $ bookmarks
* /
public function addBookmarks(Collection $ bookmarks)
{
foreach($书签为$书签){
$ this-> bookmarks-> add($ bookmark);
}
}

/ **
* @param Collection $ bookmarks
* /
public function removeBookmarks(Collection $ bookmarks)
{
foreach($ bookmarks as $ bookmark){
$ this-> bookmarks-> removeElement($ bookmark);
}
}

您现在可以删除并添加收藏中给出的广告这个:

  $ user-> addBookmarks(new ArrayCollection(array($ advert))); 

始终建议定义加法器因为许多Doctrine组件将需要它们,例如非常有用的DoctrineObject,由DoctrineModule用于Zend 2的Hydrator


I have 2 tables called Advert and User. The User Id gets written into the Advert Table. I have now created a third table called Bookmark. The table got 2 columns, advert_id and user_id. When I see an Advert I like, I can add a Bookmark to be able to find it easier in my Private Section. When I am in my Private Section to see my Bookmarks, I want to see the Advert Details straight away, so in my Repository I want to create a Join to read the information from the Advert Table. I thought this will be a OneToOne Relationship. I also have to make sure that if the Advert gets deleted, then all the Bookmarks need to be deleted, so I thought its a Bi-directional relationship. So I have below:

Entity/Bookmark.php

 /**
 * Bookmark
 *
 * @ORM\Table(name="bookmark")
 * @ORM\Entity(repositoryClass="Advert\Repository\BookmarkRepository")
 */
class Bookmark
{
 /**
 * @var integer
 * @ORM\Id
 * @ORM\Column(name="advert_id", type="integer", nullable=false)
 * @ORM\OneToOne(targetEntity="Advert", mappedBy="bookmark")
 * @ORM\JoinColumn(name="advert_id", referencedColumnName="id")
 */
 private $advertId;

/**
 * @var integer
 * @ORM\Id
 * @ORM\Column(name="user_id", type="integer", nullable=false)
 * @ORM\OneToOne(targetEntity="User")
 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
 */
 private $userId;


 public function setAdvertId($advertId)
 {
    $this->advertId = $advertId;
    return $this;
 }


 public function getAdvertId()
 {
    return $this->advertId;
 }


 public function setUserId($userId)
 {
    $this->userId = $userId;
    return $this;
 }


 public function getUserId()
 {
    return $this->userId;
 }

Entity\Advert.php

/** Advert
 * 
 * @ORM\Table(name="advert")
 * @ORM\Entity(repositoryClass="Advert\Repository\AdvertRepository")
 */

class Advert
{
  /**
   * @var integer
   *
   * @ORM\Column(name="id", type="integer", nullable=false)
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="IDENTITY")
   */
    private $id;

 /**
   * @ORM\OneToOne(targetEntity="Bookmark", inversedBy="advert")
   * @ORM\JoinColumn(name="id", referencedColumnName="advert_id")
   **/
    private $bookmark;

public function setBookmark($bookmark)
{
    $this->bookmark = $bookmark;
    return $this;
}


public function getBookmark()
{
    return $this->bookmark;
}



public function addBookmark($bookmark)
{
    $this->bookmark->add($bookmark);
}


public function removeBookmark($bookmark)
{
    $this->bookmark->removeElement($bookmark);   
}

Advert\Repository\Advert\Repository.php

class BookmarkRepository extends EntityRepository
{
  public function getBookmarksByUserIds($userId)
  {
    $query =$this->_em->getRepository($this->getEntityName())->createQueryBuilder('b')
                            ->join('b.advertId', 'a')
                            ->andWhere('a.userId=:userid')
                            ->setParameter('userid',$userId)       
            ;
    return $query->getQuery()->getResult();
  }

What do I do wrong or where is my missunderstanding? I get the Error Message:

Advert\Entity\Bookmark has no association named advertId

As I said, the table Bookmark gets only filled, when I click on "Add Advert to Bookmarks". I need a Join to be able to display the Advert Details when I click on "Show my Bookmarks" and if an Advert or a User gets deleted, all Bookmarks need to be removed from the Bookmark table. Is this a OneToOne Bi-directional relationship and what is wrong?

UPDATE 1 BELOW NOT WORKING

I have updated the 2 Files below, but I do not get any Bookmarks shown. Instead I should see a list of Bookmarked adverts plus the advert details. I have not even tried yet to get my Service to "Bookmark Advert" or the method to check if an Advert is bookmarked working again. I got it working before, but I guess I am just really confused now.

AdvertController.php

public function watchlistAction()
{
    $user_id = $this->zfcUserAuthentication()->getIdentity()->getId();
    $adverts = $this->getEntityManager()->getRepository('Advert\Entity\User')->findBookmarksByUserId($user_id);
        return new ViewModel(array(
            'adverts' => $adverts,
        ));
}

Repository\UserRepository.php

class UserRepository extends EntityRepository
{

  public function findBookmarksByUserId($userId)
  {
      $query =$this->_em->getRepository($this->getEntityName())->createQueryBuilder('b')
                            ->join('b.bookmarks', 'a')
                            ->join('b.adverts', 'c')
                ->andWhere('a.user=:userid')
                ->setParameter('userid',$userId)       
            ;
      return $query->getQuery()->getResult();
  }

UPDATE 2 BELOW WORKING

You were right, I don't need the UserRepository Query see the List of Bookmarked Adverts. I just had to change the

AdvertController.php

public function watchlistAction()
{
        $user_id = $this->zfcUserAuthentication()->getIdentity()->getId();
        // get User by reference (no queries executed)
        $user = $this->getEntityManager()->getReference('Advert\Entity\User' , $user_id);
        $adverts = $user->getBookmarks();

        return new ViewModel(array(
            'adverts' => $adverts,
        ));
}

Good news also, in the moment I delete an Advert, the Bookmark gets automatically removed in the Bookmark Database table. Now I only have to find out how to add the Bookmark, so I will have to change my Service. As soon I get this working I will update this post for others to see.

UPDATE 3 BELOW NOT WORKING

Unfortunately I do not get the below 3 Methods in my Service working. I obviously have to now pick 1 record, to either check the Status (Bookmarked already or not), remove the Bookmark (defined by advertId) or add a Bookmark (defined by advertId)

public function checkAdvertBookmarkStatus($advertId)
{
    $userId = $this->getUserEntity()->getId();  
    // get User by reference (no queries executed)
    $user = $this->getEntityManager()->getReference('Advert\Entity\User' , $userId);

    $bookmarkStatus = $this->getEntityManager()->getRepository('Advert\Entity\User')
                                         ->findOneBy(array('advert' => $advertId, 'userId' => $userId));

    return $bookmarkStatus;
}  

   public function saveAdvertBookmark($advertId)
{
    $bookmark = new UserEntity();
    $userId = $this->getUserEntity()->getId();

 //   $bookmark->addBookmark($advertId);
    $bookmark->setAdvertId($advertId);
    $bookmark->setUserId($userId);

    # write new bookmmark to database tbl bookmark
    $this->getEntityManager()->persist($bookmark);
    $this->getEntityManager()->flush();
}


public function removeAdvertBookmark($advertId)
{
    $bookmark = new UserEntity();
    $userId = $this->getUserEntity()->getId();
    $bookmark = $this->getEntityManager()->getRepository('Advert\Entity\Bookmark')
                                         ->findOneBy(array('advertId' => $advertId, 'userId' => $userId));

    # remove bookmmark from tbl bookmark
    $this->getEntityManager()->remove($bookmark);
    $this->getEntityManager()->flush();

}

I suppose the answer is in the Tutorial, which I keep reading, but I do not understand it fully. I was able to add Bookmarks before, when I was using the BookmarkEntity, but I have no idea how to do it via the UserEntity

解决方案

A OneToOne relationship would be the wrong choice here, this would mean that a user can bookmark only one advert and that an advert can only be bookmarked by one user. Because a user should be able to bookmark many adverts and an advert should be bookmarked by many users, you need a ManyToMany relationship.

You idea to create a mapping table bookmarks is not wrong if you work with a database. However, you don't need to create it as an entity in Doctrine. You can simply add Adverts in an association called bookmarks in User to display the bookmarked Adverts and vice versa:

User Entity:

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
private $id;

/**
 * @ORM\ManyToMany(targetEntity="Application\Entity\Advert", inversedBy="bookmarks", cascade={"persist"})
 * @ORM\JoinTable(name="bookmarks",
 *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="advert_id", referencedColumnName="id")}
 *      )
 */
private $bookmarks;

Advert Entity

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
private $id;

/**
 * @ORM\ManyToMany(targetEntity="Application\Entity\User", mappedBy="bookmarks", cascade={"persist"})
 * @ORM\JoinTable(name="bookmarks",
 *      joinColumns={@ORM\JoinColumn(name="advert_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}
 *      )
 */
private $bookmarks;

You might want to read this article, too: http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html

Edit: How to add and remove bookmarks

Associations in Doctrine are something entirely different from fields, although both are properties in your Entity. To handle bookmarks you add or remove the Advert Entity in your User Entity directly. For example:

$bookmarks = $user->getBookmarks();
$bookmarks[] = $advert;

This would add a bookmark to the user and will be stored as soon as you persist and flush. To make this even easier, you can define remover and adder:

Use statements:

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

and the code:

/**
 * @param Collection $bookmarks
 */
public function addBookmarks(Collection $bookmarks)
{
    foreach ($bookmarks as $bookmark) {
        $this->bookmarks->add($bookmark);
    }
}

/**
 * @param Collection $bookmarks
 */
public function removeBookmarks(Collection $bookmarks)
{
    foreach ($bookmarks as $bookmark) {
        $this->bookmarks->removeElement($bookmark);
    }
}

You can now remove and add adverts given in collection like this:

$user->addBookmarks(new ArrayCollection(array($advert)));

It is always recommended to define adder and remover in toMany relationships, because many Doctrine components will need them, for example the very useful DoctrineObject, a hydrator used by DoctrineModule for Zend 2

这篇关于Doctrine2 ORM OneToOne不工作UPDATE更改为ManyToMany但不完全正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆