【发布时间】:2019-02-18 21:36:18
【问题描述】:
在 symfony 2.8 应用程序中,我将以下类层次结构配置为单表继承:
parent: App\Entity\AbstractUser
child1: App\Entity\UserClient
child2: App\Entity\UserGuest
此外,上面的每个类都与类 App\Entity\Profile 具有 oneToOne 关系。
基于以上内容,我对 profiles 表加入了 users 表的原生查询。 目标是在一次查询中获取个人资料数据和相关的用户数据。
它确实工作了一段时间,但在某个时候停止工作。可能在学说包更新之后。
现在我下面的代码抛出以下异常:The provided class "App\Entity\AbstractUser" is abstract, and can not be instantiated。
我该怎么做才能让它再次工作?
这是我的代码:
$rsm = new ResultSetMapping;
$rsm->addEntityResult('App\Entity\AbstractUser', 'br');
$rsm->addFieldResult('br', 'user_id', 'id');
$sql = "
SELECT
rsa.id AS profile_id,
br.id AS user_id
FROM profiles rsa
LEFT OUTER JOIN users br ON rsa.id = br.profile_id
";
try {
$query = $this->_em->createNativeQuery($sql, $rsm);
$results = $query->getResult();
} catch (\Exception $e) {
throw $e;
}
以下是教义定义:
// Resources/config/doctrine/AbstractUser.orm.yml
App\Entity\AbstractUser:
type: entity
table: users
inheritanceType: SINGLE_TABLE
discriminatorColumn:
name: type
type: string
length: 30
nullable: false
discriminatorMap:
client: App\Entity\UserClient
guest: App\Entity\UserGuest
fields:
id:
id: true
type: integer
generator:
strategy: AUTO
# oneToOne association
oneToOne:
profile:
targetEntity: App\Entity\Profile
cascade: ['persist','remove']
joinColumn:
name: profile_id
referencedColumnName: id
nullable: false
unique: false
// Resources/config/doctrine/UserClient.orm.yml
App\Entity\UserClient:
type: entity
// Resources/config/doctrine/UserGuest.orm.yml
App\Entity\UserGuest:
type: entity
// Resources/config/doctrine/Profile.orm.yml
App\Entity\Profile:
type: entity
table: profiles
fields:
id:
id: true
type: integer
generator:
strategy: AUTO
【问题讨论】:
-
$rsm->addEntityResult('App\Entity\AbstractUser', 'br');此行不会导致结果映射器尝试使用查询结果创建AbstractUser的实例吗?为什么不将 AbstractUser 更改为 User,让它成为一个实体。结果映射器应将其识别为可区分类型(基于配置和列)并自动加入映射实体。 (如果ResultSetMapping不支持,请查看\Doctrine\ORM\QueryBuilder)。 -
另外,see here,最后引用的要点:
If no discriminator map is provided, then the map is generated automatically. The automatically generated discriminator map contains the lowercase short name of each class as key.- 所以你可以删除discriminatorMap配置,让 Doctrine 在内部处理它的创建。 -
谢谢@rkeet。 “为什么不将 AbstractUser 更改为 User”是什么意思?儿童班之一?我已经尝试过,例如
$rsm->addEntityResult('App\Entity\UserClient', 'br');查询有效,但结果集仅包含 UserClient 实体,无论记录是什么鉴别器类型。 -
使
User成为一个实体。不是abstract,不是MappedSuperclass,而是一个可实例化的实体。如果您随后$rsm->addEntityResult('App\Entity\User', 'br'),您应该获得User、UserClient和UserGuest实体的结果集。为了防止创建普通的User,只需确保通过不创建user/addURI/endpoint 就无法创建它。 -
@rkeet 如果我这样做会出现后续问题:
Entity 'App\Entity\AbstractUser' has to be part of the discriminator map of 'App\Entity\AbstractUser' to be properly mapped in the inheritance hierarchy. Alternatively you can make 'App\Entity\AbstractUser' an abstract class to avoid this exception from occurring
标签: doctrine-orm