如何使用Doctrine和Symfony2从数据库视图生成实体

9
我正在尝试使用Symfony2文档中描述的标准控制台命令从数据库生成实体:http://symfony.com/doc/current/cookbook/doctrine/reverse_engineering.html
php app/console doctrine:mapping:convert --from-database --force yml "src/My/HomeBundle/Resources/config/doctrine/metadata/orm"
php app/console doctrine:mapping:import MyHomeBundle yml
php app/console doctrine:generate:entities MyHomeBundle

此后,所有的表都可以正确生成。问题是它不会为数据库视图生成实体。例如,当我自己将yml文件添加到src/My/HomeBundle/Resources/config/doctrine/metadata/orm中时:
UserInGroup:
  type: entity
  table: user_in_group_view
  fields:
    id:
      id: true
      type: integer
      unsigned: false
      nullable: false
      generator:
        strategy: IDENTITY
    userId:
      type: integer
      unsigned: false
      nullable: false
      column: user_id
    userGroupId:
      type: integer
      unsigned: false
      nullable: false
      column: user_group_id
  lifecycleCallbacks: {  }

当运行 php app/console doctrine:generate:entities MyHomeBundle 时,我会得到这个异常:
Notice: Undefined index: My\HomeBundle\Entity\UserInGroup in C:\Users\ThisIsMe\Projects\SymfonyTestProject\vendor\doctrine\lib\Doctrine\ORM\Mapping\Driver\AbstractFileDriver.php line 121

类似的问题在这里发布:如何在Symfony 2中设置用于数据库视图的实体(Doctrine)
我知道我可以创建Entity类,但我希望能够生成此内容,以便如果更改视图,则可以重新生成Entity类。有什么建议吗?
4个回答

2

现在你只需要创建你的orm文件。你还需要完成2个步骤。我会从头开始给你完整的步骤。

在进行此操作之前,请删除您先前创建的ORM目录中的所有yml文件。

我希望MyHomeBundle是你的bundle名称。

1).php app/console doctrine:mapping:convert yml ./src/My/HomeBundle/Resources/config/doctrine --from-database --force 

  Symfony2 generate entity from Database

 2).php app/console doctrine:mapping:import MyHomeBundle yml

 3).php app/console doctrine:generate:entities MyHomeBundle

希望这能帮到你。

这些是我在问题中描述的相同步骤,并且它将为所有表生成实体,而不是视图。区别在于生成的yml文件的目标路径。我为了确认曾尝试过您的解决方案,但它没有解决问题,只有表被转换为实体。我知道Doctrine(和Symfony)的早期版本可以轻松地从视图生成实体。 - Kosta

0

我知道这是一个老问题,但我找到了一个技巧(Symfony 6),可以从SQL视图生成实体(我使用SQL Server数据库)。

因此,我修改了doctrine bundle的SQLServerPlatform.php文件的两个方法。

public function getListTablesSQL()
{
    // "sysdiagrams" table must be ignored as it's internal SQL Server table for Database Diagrams
    // Category 2 must be ignored as it is "MS SQL Server 'pseudo-system' object[s]" for replication
    return 'SELECT name, SCHEMA_NAME (uid) AS schema_name FROM sysobjects'
        . " WHERE type = 'V' AND name != 'sysdiagrams' AND category != 2 ORDER BY name";
}

我将视图的where条件参数“U”更改为“V”。

对于方法getListTableColumnsSQL(),我们在这里将where条件的“U”参数更改为“V”。

public function getListTableColumnsSQL($table, $database = null)
{

    return "SELECT    col.name,
                      type.name AS type,
                      col.max_length AS length,
                      ~col.is_nullable AS notnull,
                      def.definition AS [default],
                      col.scale,
                      col.precision,
                      col.is_identity AS autoincrement,
                      col.collation_name AS collation,
                      CAST(prop.value AS NVARCHAR(MAX)) AS comment -- CAST avoids driver error for sql_variant type
            FROM      sys.columns AS col
            JOIN      sys.types AS type
            ON        col.user_type_id = type.user_type_id
            JOIN      sys.objects AS obj
            ON        col.object_id = obj.object_id
            JOIN      sys.schemas AS scm
            ON        obj.schema_id = scm.schema_id
            LEFT JOIN sys.default_constraints def
            ON        col.default_object_id = def.object_id
            AND       col.object_id = def.parent_object_id
            LEFT JOIN sys.extended_properties AS prop
            ON        obj.object_id = prop.major_id
            AND       col.column_id = prop.minor_id
            AND       prop.name = 'MS_Description'
            WHERE     obj.type = 'V'
            AND       " . $this->getTableWhereClause($table, 'scm.name', 'obj.name');
}

也许这会对某人有所帮助。


0

遇到了相同的问题,我使用 XML 而不是 YML,但应该是一样的。

检查你的 ORM 实体是否包含正确的路由名称,例如:

<entity name="Myapp\MyrBundle\Entity\MyEntity" table="myentity">

因为当我从数据库生成我的ORM时,名称就是这样的:

<entity name="MyEntity" table="myentity">

所以Doctrine没有理解正确的路径。

希望我表达清楚了,这会对你有所帮助!


检查过了。我想过了,试了不同的组合,但是没有成功。不过还是谢谢你。 - Kosta
你能粘贴实体 UserInGroup 吗? - Snroki
问题在于我不想自己创建实体,而是让Doctrine为我创建。最终,我已经创建了实体并正在使用它,但问题仍然存在。 - Kosta
好的,但问题是,如果你已经运行了doctrine:mapping:import命令,你的实体目录中应该有实体了。generate:entities只会生成实体的getter和setter,所以可能实体的命名空间或类名不正确(这可能解释了你的错误),但是如果你成功获取到你的实体,那就太好了。 - Snroki
没错!但它们不在那里,这就是问题和我的问题所在。请注意,数据库表的实体已经正确生成 - 问题出在数据库视图上。 - Kosta

-1

正如您在这里所看到的: http://symfony.com/doc/current/cookbook/doctrine/reverse_engineering.html 从数据库到实体的反向工程过程尚未完全实现:

“正如Doctrine工具文档所说,反向工程是启动项目的一次性过程。基于字段、索引和外键约束,Doctrine能够转换大约70-80%的必要映射信息。Doctrine无法发现反向关联、继承类型、将外键作为主键的实体或关联操作上的语义操作,例如级联或生命周期事件。之后需要对生成的实体进行一些额外的工作,以设计每个实体以适应您的领域模型特定性。”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接