Doctrine DBAL ->execute() 和 Hydration,DB2 字段名称包括“#”

Posted

技术标签:

【中文标题】Doctrine DBAL ->execute() 和 Hydration,DB2 字段名称包括“#”【英文标题】:Doctrine DBAL ->execute() and Hydration with DB2 field names including '#' 【发布时间】:2016-09-20 17:12:15 【问题描述】:

我正在尝试使用 Doctrine DBAL 实现模型/映射器类型的交互,但遇到了一些问题。我的一些列名末尾有一个“#”。更改名称不是一种选择。 $'COL1#' 语法适用于常规变量,但 php 似乎很难将其用作对象属性。

解析错误:语法错误,意外的'$',期望变量(T_VARIABLE in...

如何为字段名称中带有井号标签的表创建模型?

【问题讨论】:

问题 1:您是否配置了 Doctrine 实体?问题 2:您是否尝试使用 Zend\Stdlib\Hydrator\ClassMethods 水合器来水合实体? @ceadreak 由于这个问题,我开始使用 Doctrine 实体,但这些数据库表已有近 40 年的历史,并且几乎不存在关系。此外,我们还有不使用 PHP(其他语言但相同的表)工作的开发人员,我不能指望他们在更改数据库时记得更改实体。所以我相信实体是不可能的。至于ClassMethods,我用它来补充水分,但我仍然必须遍历每一行。 您不能在 mysql 中创建视图并将列重命名为更友好的名称(没有#)...? Doctrine 支持为您的模型使用视图。 【参考方案1】:

我看不出在没有实体的情况下使用 Doctrine 的意义。

如果您的数据库真的很旧(40 岁,天哪!),您应该使用数据库抽象层/框架,例如 Zend DB(抱歉您使用的是 ZF2)或 Aura(@ 987654321@)。

但如果你真的想使用 Doctrine,你应该手动创建实体,并使用魔法 setter - getter 来处理特殊字段并访问/水合你的实体。

编辑

想象你的数据库有一个表 Clients 和 2 个字段:idname#1

class Client

   protected $id;
   protected $name1;

   public function __set()
   
       // here you can set unknown properties
       // remove '#' e.g ...
   

   public function setName1($name1)
   
       $this->name1 = $name1;

       return $this;
   

   public function getName1()
   
       return $this->name1;
   

   // ... other accessors


用法:

$results = clients_query_result ...
$hydrator = new ClassMethods();
$clients = [];

foreach ($results as $result)

    $client = new Client();
    $clients[] = $hydrator->hydrate($result, $client);


// that's it, now you have a collection of Client objects

【讨论】:

谢谢,我使用的是 Doctrine DBAL 但不是 Doctrine ORM。我想我可以使用Zend\DBZend\Db\ResultSet\HydratingResultSet 来代替,但是据我所知,这仍然会循环两次结果集。我并不是真的在问我的具体情况。我只是好奇,如果每个人在使用 hydrators 时都会循环访问他们的查询结果两次,或者是否还有其他一些我不知道的方法/技巧。循环两次似乎很愚蠢,但也许一般的概念是拥有一个模型值得额外的开销。 这取决于您的结果集...如果是对象或数组,您可以轻松使用 ClassMethods 水合器。但是对于这种情况,您不需要使用 Doctrine。不可能从实体创建架构,也不可能从架构创建出色的实体......我更新了我的答案,向您展示了实体和 ClassMethods 水合的示例。希望它会有所帮助 ClassMethods 无法处理主题标签。我必须使用Zend\Stdlib\Hydrator\ArraySerializable 并配置我的exchangeArraygetArrayCopy() 方法,以便它们将关联从我的表名映射到我的对象属性。【参考方案2】:

您可以create views in MySQL 并将您的列重命名为在这些视图中更友好的名称(没有#)...?像这样,您不必更改原始表,但仍然可以解决这些命名问题。

Doctrine 还为您的模型支持the use of views。

许多数据库支持在语义上映射到某些表的视图上的所有 CRUD 操作。您可以为所有有问题的表和列名创建视图以...

它们指的是不同的场景,但使用视图的相同解决方案可能会有所帮助。

据我了解,您只是在使用 Doctrine DBAL,但无论如何 here some more information 在将 MySQL 视图与教义 ORM 结合使用时,它可能会有所帮助(对您或其他人)。

【讨论】:

谢谢,这不是我最终采用的解决方案,但它仍然是解决问题的可能解决方案。这就是我将其标记为答案的原因。

以上是关于Doctrine DBAL ->execute() 和 Hydration,DB2 字段名称包括“#”的主要内容,如果未能解决你的问题,请参考以下文章

工匠迁移错误“找不到类'Doctrine\\DBAL\\Driver\\PDOMySql\\Driver'”,

使用 Doctrine/DBAL 迁移数据库时如何修复未知数据库错误?

执行多个查询时的 Doctrine (DBAL) 错误处理

PostgreSQL 咨询锁不适用于 Doctrine 的 DBAL

在作曲家 laravel 上安装依赖项(doctrine/dbal)

使用 insert() 方法通过 PHP Doctrine\DBAL 2 插入 DateTime 值