Symfony2 DiscriminatorColumn 作为外键并加载实体

Posted

技术标签:

【中文标题】Symfony2 DiscriminatorColumn 作为外键并加载实体【英文标题】:Symfony2 DiscriminatorColumn as Foreign Key and load Entity 【发布时间】:2015-05-11 23:54:46 【问题描述】:

我有一个 InheritanceTypeSINGLE_TABLE,类型基于另一个实体的 FK。

当我转到附件实体的详细信息页面时,它会加载产品实体。 但是当我尝试通过 Item Attachmentcollection 访问 Product 实体时,产品为 NULL。

视图的控制器正在使用 '$entity = $em->getRepository('projectTestBundle:Item')->find($id);' '$entity = $em->getRepository('projectTestBundle:Attachment')->find($id);'

下面的转储和文件。

附件详细信息页面上的实体转储

ImageAttachment #361 ▼
  #product: Product #390 ▼
    +__isInitialized__: false
    #id: "IMAGE"
    #name: null
     …4
  
  -id: 1
  #name: "Test"
  #item: Item #372 ▶

通过集合在项目详细信息页面上转储实体

  ImageAttachment #367 ▼
      #product: null
      -id: 1
      #name: "Test"
      #item: Item #323 ▶
    

附件.php

namespace project\TestBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Attachment
 *
 * @ORM\Table(name="attachments")
 * @ORM\Entity
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="product", type="string")
 * @ORM\DiscriminatorMap("IMAGE" = "project\TestBundle\Entity\ImageAttachment", "TEXT" = "project\TestBundle\Entity\TextAttachment")
 * @ORM\Entity(repositoryClass="project\TestBundle\Entity\AttachmentRepository")
 */
class Attachment

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

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\ManyToOne(
     *     targetEntity="Item",
     *     inversedBy="attachments"
     * )
     * @ORM\JoinColumn(
     *     name="item_id",
     *     referencedColumnName="id",
     *     nullable=false
     * )
     */
    protected $item;  

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    
        return $this->id;
    

    /**
     * Set name
     *
     * @param string $name
     * @return Attachment
     */
    public function setName($name)
    
        $this->name = $name;

        return $this;
    

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    
        return $this->name;
    

    /**
     * Set item
     *
     * @param \project\TestBundle\Entity\Item $item
     * @return Attachment
     */
    public function setItem(\project\TestBundle\Entity\Item $item)
    
        $this->item = $item;

        return $this;
    

    /**
     * Get item
     *
     * @return \project\TestBundle\Entity\Item
     */
    public function getItem()
    
        return $this->item;
    

?>

ImageAttachment.php(TextAttachemnt 是同一个类,现在只是简单的文本更改。)

namespace project\TestBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Attachment
 *
 * @ORM\Entity
 */
class ImageAttachment extends Attachment

    /**
     * @ORM\ManyToOne(targetEntity="Product",cascade="persist",fetch="EXTRA_LAZY")
     * @ORM\JoinColumn(name="product", referencedColumnName="product", nullable=true)
     */
    protected $product;

    /**
     * Set product
     *
     * @param \project\TestBundle\Entity\Product $product
     * @return ImageAttachment
     */
    public function setProduct(\project\TestBundle\Entity\Product $product = null)
    
        $this->product = $product;

        return $this;
    

    /**
     * Get product
     *
     * @return \project\TestBundle\Entity\Product
     */
    public function getProduct()
    
        return $this->product;
    

    /**
     * Set item
     *
     * @param \project\TestBundle\Entity\Item $item
     * @return ImageAttachment
     */
    public function setItem(\project\TestBundle\Entity\Item $item)
    
        $this->item = $item;

        return $this;
    

    /**
     * Get item
     *
     * @return \project\TestBundle\Entity\Item
     */
    public function getItem()
    
        return $this->item;
    

Item.php

namespace project\TestBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Item
 *
 * @ORM\Table(name="items")
 * @ORM\Entity
 * @ORM\Entity(repositoryClass="project\TestBundle\Entity\ItemRepository")
 */
class Item

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

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\OneToMany(
     *     targetEntity="Attachment",
     *     mappedBy="item",
     *     cascade="persist", "remove",
     *     orphanRemoval=true
     * )
     */
    protected $attachments;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    
        return $this->id;
    
    /**
     * Constructor
     */
    public function __construct()
    
        $this->attachments = new \Doctrine\Common\Collections\ArrayCollection();
    

    /**
     * Set name
     *
     * @param string $name
     * @return Item
     */
    public function setName($name)
    
        $this->name = $name;

        return $this;
    

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    
        return $this->name;
    

    /**
     * Add attachments
     *
     * @param \project\TestBundle\Entity\Attachment $attachments
     * @return Item
     */
    public function addAttachment(\project\TestBundle\Entity\Attachment $attachments)
    
        $this->attachments[] = $attachments;
        $attachments->setItem($this);
        return $this;
    

    /**
     * Remove attachments
     *
     * @param \project\TestBundle\Entity\Attachment $attachments
     */
    public function removeAttachment(\project\TestBundle\Entity\Attachment $attachments)
    
        $this->attachments->removeElement($attachments);
    

    /**
     * Get attachments
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getAttachments()
    
        return $this->attachments;
    

【问题讨论】:

【参考方案1】:

我认为您的问题是您的 Product 实体是延迟加载的,在您的附件实体中。为避免这种情况,您应该使用自定义方法来查找您的实体,您离开的位置加入您的产品,如下所示:

/* Controller*/
$entity = $em->getRepository('projectTestBundle:Item')->customFind($id);

/* ItemRepository */
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder();
$qb
        ->select('Item','attachment')
        ->from('projetTestBundle\Entity\Item','Item')
        ->leftJoin('Project.attachment','attachment')
        ;
    $q = $qb->getQuery();
    return $q->getResult();    

希望对你有帮助

【讨论】:

感谢您的示例,但这不起作用。附件类不知道 Product,因为附件类的 Product 是 DiscriminatorColumn。我想弄清楚如何使它能够用作 DiscriminatorColumn 和普通的 entityMap

以上是关于Symfony2 DiscriminatorColumn 作为外键并加载实体的主要内容,如果未能解决你的问题,请参考以下文章

Symfony2 无法连接到 sqlite

找不到 Symfony2 组件类

Symfony2 - 访问被拒绝

Symfony2 / SonataUserBundle - 注册后自动登录

Symfony2 OneToMany 关系

Symfony2无效形式没有错误