简体   繁体   English

教义2中的ManyToOne关系

[英]ManyToOne Relationship in Doctrine 2

I am trying to get into Doctrine 2 with Zend Framework 2. I have 2 Database Tables: 我正在尝试使用Zend Framework 2进入教义2。我有2个数据库表:

advertable 可广告的

  • id ID
  • advert_title advert_title
  • advert_user_id advert_user_id

user table 用户表

  • id ID
  • username 用户名

I now have a form to add a new advert and want to inject the advert_user_id, when I save the advert in my table. 现在,我有一个添加新广告的表单,并希望在将广告保存到表中时注入advert_user_id。 I have created 2 Entities: 我创建了2个实体:

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

/**
 * @var integer
 *
 * @ORM\Column(name="advert_user_id", type="integer", nullable=false)
 */
private $advertUserID;

/** 
 * @ORM\ManyToOne(targetEntity="User", inversedBy="adverts") 
 * @ORM\JoinColumn(name="advert_user_id", referencedColumnName="id")
 */ 
protected $user;


/**
 * Set advertUserID
 *
 * @param integer $advertUserID
 * @return Advert
 */

 public function setAdvertUserID($advertUserID)
{
    $this->advertUserID = (int) $advertUserID;

    return $this;
}

/**
 * Get advertUserID
 *
 * @return integer
 */
public function getAdvertUserID()
{
    return $this->advertUserID;
}

/** 
 * Set user 
 * 
 * @param \Advert\Entity\User $user 
 * @return Advert 
 */ 
public function setUser(\Advert\Entity\User $user = null) 
{ 
    $this->user = $user; 

    return $this; 
} 

/** 
 * Get user 
 * 
 * @return \Advert\Entity\User 
 */ 
public function getUser() 
{ 
    return $this->user; 
}

And the following User Entity 和以下用户实体

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

 /**
 * @ORM\OneToMany(targetEntity="Advert", mappedBy="user")
 */
private $adverts;

In my controller I now try to do the following: 现在,在我的控制器中尝试执行以下操作:

if ($form->isValid()) 
{
  $advert->setAdvertUserID('13');  //Static for testing     
  $this->getEntityManager()->persist($advert));
  $this->getEntityManager()->flush();

Unfortunately the entry in the database is always null. 不幸的是,数据库中的条目始终为空。 If I delete the @ORM\\ManyToOne $user in my Advert Entity it works. 如果我在广告实体中删除@ORM \\ ManyToOne $ user,它将起作用。 The setup does allow me to read out the Username through the Advert Entity, so why can I not save the User ID in my advert table? 该设置确实允许我通过广告实体读出用户名,所以为什么不能在广告表中保存用户ID?

First, I would recommend not to name tables and columns explicitely (unless you have a good reason). 首先,我建议不要显式命名表和列(除非您有充分的理由)。 Also you usually don't need to specify JoinColumn s. 同样,您通常不需要指定JoinColumn Let Doctrine handle those things, it will make life much easier. 让教义来处理这些事情,它将使生活更加轻松。

Next, your entities should both have getters and setters for each column or relation. 接下来,您的实体对于每个列或关系都应同时具有getter和setter。 Also, the User entity should have a constructor which initializes the $adverts field to a ArrayCollection object. 此外, User实体应具有一个构造函数,该构造函数将$ adverts字段初始化为ArrayCollection对象。 (Doctrine has a CLI command for entity method generation; don't know how it's integrated with ZF, in SF2 it's doctrine:generate:entities ) (Doctrine有一个用于生成实体方法的CLI命令;不知道它如何与ZF集成,在SF2中是doctrine:generate:entities

Now, for the actual problem: The reason why you can't access the user from the advert object is because you have never set that relation. 现在,针对实际问题:无法从advert对象访问user的原因是因为您从未设置该关系。 In your setter, you must either pass an entity or a reference to that entity (google for $EM->getReference(…) ). 在您的设置器中,您必须传递一个实体或对该实体的引用 (对于$EM->getReference(…) Google)。 Only then will Doctrine be able to autoload the related entity. 只有这样,Doctrine才能自动加载相关实体。

If you only store the ID of the related object, you would have to fetch the entity manually each time because Doctrine doesn't even know of the relation between the entities. 如果仅存储相关对象的ID,则每次都必须手动获取实体,因为Doctrine甚至都不知道实体之间的关系。

I understand you have the user_id stored in your session and you want to save the user with the advert without first getting the whole user entity from the database. 我了解您在会话中存储了user_id,并且您想在不首先从数据库中获取整个用户实体的情况下,将带有广告的用户保存下来。 That sounds like a good idea and one query less to execute. 这听起来像是个好主意,而执行一个查询就更少了。

The way to do this is like this: 这样做的方法是这样的:

First clean up your advert entity from the unnecessary and not according to Doctrine2 specs $advertUserID related stuff :) 首先从不必要的地方清除您的advert实体,而不是根据Doctrine2规范$advertUserID相关的东西:)

/** 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\ManyToOne(targetEntity="User", inversedBy="adverts") 
     * @ORM\JoinColumn(name="advert_user_id", referencedColumnName="id")
     */ 
    protected $user;

    /** 
     * Set user 
     * 
     * @param \Advert\Entity\User $user 
     * @return Advert 
     */ 
    public function setUser(\Advert\Entity\User $user = null) 
    { 
        $this->user = $user; 

        return $this; 
    } 

    /** 
     * Get user 
     * 
     * @return \Advert\Entity\User 
     */ 
    public function getUser() 
    { 
        return $this->user; 
    }
}

Then add user by reference to your advert: 然后通过参考您的广告添加用户:

$user_id = 13
$entityManager = $this->getEntityManager();

// get User by reference (no queries executed)
$user = $entityManager->getReference('Advert\Entity\User' , $user_id);

// set the User in the Advert using the setUser method
$advert->setUser($user); 

// Persist and flush!
$entityManager->persist($advert));
$entityManager->flush();

Now you can find a user_id in the advert table and no additional queries were executed to do this. 现在,您可以在advert表中找到一个user_id,而无需执行其他任何查询。 Read more on reference proxies here in the Doctrine2 documentation . 在Doctrine2文档中阅读有关参考代理的更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM