如何从没有鉴别器列的教义实体扩展


How to extend from Doctrine-Entity without Discriminator-Column

挑战:

我想以这种方式重用具有类继承的第三方捆绑包的现有实体,仍然只剩下一个表,不需要额外的东西。这意味着:没有鉴别器列,也没有 JOIN。相反,只有最终的继承最多的类应该是可查询的,向基实体添加一些属性,并且只使用一个包含所有列的表,这些列是从自身和继承添加到实体的

这里要明确一点:我对经典表继承不感兴趣。我只想以这种方式用其他列扩展基类,即数据库中的表表示所有需要的列的总和。

无需能够创建基本实体的实例。

对于那些感兴趣的人,我在下面解释原因。

第三方库的基本实体:

Sylius'UserEntity (TableName: "sylius_user")
============================================
ColA, ColB, ColC

我的班级:

MyProject'UserEntity : Sylius'UserEntity (TableName: "user") <---- overwrite the base table name
========================================
ColD, ColE, ColF

上面的模型表示最终方法:我的用户实体扩展了 syslius 的用户实体,应该在包含最终扩展实体的所有列的表"user"(而不是"user"和"sylius_user")中持久化和查询

表结构:

因此,我的 szenario 中只存在一张表。

Table "user":
=============
ColA, ColB, ColC, ColD, ColE, ColF
前 3 列是基本实体中的属性

,后 3 列是"我的"用户实体中的属性,它获得前三到继承。

我做了什么:

我的用户类如下所示:

use 'Sylius'Component'User'Model'User as BaseUser;
/**
 * User
 *
 * @ORM'Entity(repositoryClass="MyAppName'UserBundle'Repository'UserRepository")
 * @ORM'Table(name="user", uniqueConstraints= ... */
class User extends BaseUser 
{

用户存储库:

class UserRepository extends EntityRepository
{
    /**
     * @param string $usernameOrEmail
     * @return User
     */
    public function findByUsernameOrEmail($usernameOrEmail)
    {
        $qb = $this
            ->createQueryBuilder('u')
            ->where('u.username = :search OR u.email = :search')
            ->setParameter('search', $usernameOrEmail);
        try {
            return $qb->getQuery()->getSingleResult();
        }
        catch(NoResultException $e) {
            return null;
        }
    }
}

此查询导致从表"user"中选择列,但查询尝试选择列两次,每个列具有单独的表别名。生成的查询失败,因为它已中断。

教义在这里所做的,看起来像这样:

SELECT s0.ColA, s0.ColB, s0.ColC, 
u0.ColD, u0.ColE, u0.ColF
FROM user u0

正如大家所看到的,这里使用了额外的表别名"s0",而没有用表引用它。我想让多克特林做的是:

SELECT u0.ColA, u0.ColB, u0.ColC, 
u0.ColD, u0.ColE, u0.ColF
FROM user u0

何能做到这一点?

对于那些对此任务的目的感兴趣的人:

我们希望将sylius捆绑包添加到我们长期存在的symfony应用程序中,该应用程序已经拥有自己的用户捆绑包,其中包含用户模型类和现有数据。

因此,我们希望通过添加我们自己的属性来扩展sylius的用户类,以在sylius类和我们的用户类之间建立"桥梁"。两者之间的区别在属性端很小,并且仅在几列中重命名和添加一些特殊的属性和方法。但是我们有很多从用户类到其他实体的关系,如果我们能忽略表继承人员,而只是在这里充当一个简单的类重用的东西,这将不是问题。

基类是MappedSuperclass吗?

只要基类定义为MappedSuperclass,就可以简单地扩展类并将扩展类定义为Entity

默认情况下,Sylius 将实体定义为 MappedSuperclass。订阅服务器(LoadOrmMetadataSubscriber)传递每个实体,并在必要时将MappedSuperclass设置为false,这意味着当在配置中定义类时,它将MappedSuperclass更改为实体。