Php 原则DQL、类表继承和对子类字段的访问

Php 原则DQL、类表继承和对子类字段的访问,php,inheritance,doctrine-orm,doctrine,dql,Php,Inheritance,Doctrine Orm,Doctrine,Dql,我对DQL查询和实体专门化有问题 我有一个叫做拍卖的实体,它与物品有着一对一的关系。Item是电影和书籍的mappedSuperclass。我需要一个可以支持搜索引擎的查询,允许用户查找具有不同属性的拍卖和出售具有不同属性的物品。这正是使其具有挑战性的部分 问题是,即使拍卖有一个指向物品本身的关联,我也需要访问电影和书籍的特定字段。用户将指定他们要查找的项类型,但除了在DQL查询中使用的实例之外,我看不到任何使用此信息的方法 到目前为止,我已尝试使用以下查询: 从实体\拍卖中选择一个 内部连接a

我对DQL查询和实体专门化有问题

我有一个叫做拍卖的实体,它与物品有着一对一的关系。Item是电影和书籍的mappedSuperclass。我需要一个可以支持搜索引擎的查询,允许用户查找具有不同属性的拍卖和出售具有不同属性的物品。这正是使其具有挑战性的部分

问题是,即使拍卖有一个指向物品本身的关联,我也需要访问电影和书籍的特定字段。用户将指定他们要查找的项类型,但除了在DQL查询中使用的实例之外,我看不到任何使用此信息的方法

到目前为止,我已尝试使用以下查询:

从实体\拍卖中选择一个 内部连接a.i项 内连接i.b类书籍 其中,我创建了Entities\Book的实例 b.type=‘幻想’ 和 这样的查询会导致以下错误:

类实体\项没有名为bookTypes的字段或关联

这对书来说是错误的,但对物品来说却是正确的

我也试过了

从Entities\Book i中选择一个 内联拍卖会。。。 但我认为该理论要求我在SELECT和FROM语句中引用同一实体

如果这很重要,我将使用类表继承。不过,我不认为切换到单表继承会起到作用


有什么想法吗?

我也有同样的问题,如果不对每个子类使用单独的查询,然后在应用程序级别合并它们,我就找不到解决方案

有一点我可以肯定,单表继承不能解决这个问题,完全是一样的

还有另一种选择,尽管逻辑上是肮脏的。 定义超类中所需的所有字段。如果记录在逻辑上没有该字段,则该字段将为空。不是一个漂亮的景象,但是嘿,比2-3-4-更优化。。。查询。此外,在这种情况下,单表继承肯定是更好的方式更新:

我已经找到了解决这个问题的办法。有关此相关问题,请参见我的答案:


条令团队表示,他们不会对此增加支持:

该页的相关评论:

这确实很棘手。但是,这种语法本身是不起作用的, 因为可能有几个子类有一个名为d的字段, 所以教条不知道你指的是哪个领域

我要把这个关了

这个问题的要求基本上违反了OO原则

如果您真的需要在数据库中跨多个子实体进行筛选 继承,然后尝试以下操作:

挑选 r来自 根r在哪里 r、 身份证 选择 c、 身份证 从…起 儿童c 哪里 c、 字段=:值


正如马特所说,这是一个条令项目无法解决的老问题

问题在于,doctrine的DQL是一种静态类型的语言,其内部具有一定的复杂性

我们曾考虑过允许向上转换几次,但为了让它正常工作而付出的努力根本不值得,人们会滥用语法来做非常危险的事情

正如DDC-16中所述,如果不产生一些令人讨厌的问题,例如多个子类使用不同的列名定义相同的属性,那么也确实不可能理解属性属于哪个类

如果您想在CTI或JTI中过滤子类中的数据,可以使用我在中介绍的技术。将您的DQL与所有涉及的子类结合起来

在您的案例中,您需要的DQL很可能假设Entities\Book是Entities\Item的子类:

选择 A. 从…起 实体\拍卖a 内连接 a、 项目一 内连接 i、 b类书籍 哪里 i、 身份证 选择 b、 身份证 从…起 实体\Book b 哪里 b、 类型=‘幻想’
这是针对您的问题的伪代码。这并不好,但请记住SQL和DQL非常不同,遵循不同的规则。

您可以通过使用id将基本实体与继承类左键连接来轻松解决此问题:

从实体\拍卖中选择一个 内部连接a.i项 内部连接实体\Book b,b.id=i.id 内连接b.bookTypes bt 其中bt.type='Fantasy' 和 或者使用queryBuilder:

$queryBuilderb->select('a')
   ->from('Entities\Auction', 'a')
   ->innerJoin('a.item', 'i')
   ->innerJoin('Entities\Book', 'b', 'WITH', 'b.id = i.id')
   ->innerJoin('b.bookTypes', 'bt')
   ->where('bt.type = :type')
   ->andWhere(...
   ->setParameter('type', 'Fantasy');

这是基于Ian Philips在问题

中给出的答案,合并结果在这里并不完全是这样,因为我从不需要电影和书籍同时出现在我的查询结果中。我最后想到的解决方法是添加拍卖项目关系的反面并查询项目,而不是拍卖的“从实体中选择I\Book内部连接I.au”
“在哪里……”。因为我知道要查找哪个子类,所以可以相应地构建查询。不过,感谢您的回复,您的想法可能是一个很好的方法,因为在这种情况下,将继承与学说结合使用似乎没有什么意义。这是一个非常糟糕的想法,更像是一个黑客——您不需要破坏模型来修复DQL。作为最后手段,您可以始终使用本机SQL,但代价是维护一些查询。可能的重复