学说 ORM 和继承

Posted

技术标签:

【中文标题】学说 ORM 和继承【英文标题】:Doctrine ORM and inheritance 【发布时间】:2013-08-01 11:39:16 【问题描述】:

给定以下实体:

class Entity 
    protected $id;

class User extends Entity 
    /** @var Entity */
    protected $target;

class Document extends Entity 
    protected $title;

class Report extends Entity 
    protected $level;

我需要创建什么映射才能正确映射User 实体。 这里的问题是,我希望能够让User::$target 使用任何实体(因此是Entity 类型提示),并且稍后在代码中能够做出相应的响应,具体取决于它是Document 还是Report .

这也意味着,在代码中,我需要能够获取 Entity::$title(如果是 Document)或 Entity::$level(如果是 Report)。

我可以通过教义实现这一点吗?

【问题讨论】:

【参考方案1】:

这应该可以正常工作。我没有添加像 "@ORM\Entity" (http://docs.doctrine-project.org/en/latest/reference/annotations-reference.html) 这样的默认注释。 我希望这是您正在寻找的,否则请告诉我。

/**
 * @ORM\InheritanceType("SINGLE_TABLE")
 */
class Entity 
    protected $id;


class User extends Entity 
    /** 
     * @ORM\ManyToOne(targetEntity="Entity")
     * @var Entity 
     */
    protected $target;

看看:http://docs.doctrine-project.org/en/2.0.x/reference/inheritance-mapping.html 由于性能问题,您应该使用单继承而不是类表继承。

否则 Doctrine 将在实体表的子表上进行连接,因为 Doctrine 不知道“实体”具有哪种类型。比如:

 SELECT t1.id, t2.title, t3.level FROM entity t1 LEFT JOIN document t2 ON t2.id = t1.id LEFT JOIN report t3 ON t3.id = t1.id 

更多的子表将导致更多的连接 -> 慢。

这是您检查目标是文档还是报告并确定您必须访问哪个字段的方式。

// loads all users
$users = $this->em->getRepository('User')->findAll();
foreach($users as $user)
    $target = $user->getTarget()
    if($target instanceof Document)
        echo $target->getTitle(); 
    
    else if($target instanceof Report)
        echo $target->getLevel()
    

【讨论】:

以上是关于学说 ORM 和继承的主要内容,如果未能解决你的问题,请参考以下文章

XML 中的教义类继承

尝试在 zf2 / 学说下的实体之间创建继承时出现“找不到类”

ORM(学说)和SQL之间的代码比较?

ORM 继承支持

学说 ORM 和具有抽象类策略的工厂

LinQ ORM 数据对象和继承