【问题标题】:Doctrine SQL Server uniqueidentifier isn't cast as char or nvarchar when retrieved from the database从数据库检索时,Doctrine SQL Server uniqueidentifier 不会转换为 char 或 nvarchar
【发布时间】:2010-05-04 05:43:30
【问题描述】:

当我从数据库中检索具有“uniqueidentifier”类型列的记录时,Doctrine 用“null”而不是数据库中的唯一 id 填充它。

一些研究和测试已将此归结为 PDO/dblib 驱动程序问题。通过 PDO 直接查询时,返回 null 代替唯一 id。

作为参考,http://trac.doctrine-project.org/ticket/1096 对此有所了解,但是,它已在 11 个月前更新,没有针对解决方案发表评论。

http://bugs.php.net/bug.php?id=24752&edit=1 所述,解决此问题的一种方法是将列转换为字符。但是,Doctrine 似乎没有在生成模型之外公开本机字段类型,这使得在构建 sql 查询时检测 uniqueidentifier 类型并在内部强制转换它们有点困难。

有没有人找到解决方法?

【问题讨论】:

    标签: php sql-server doctrine uniqueidentifier null-uniqueidentifier


    【解决方案1】:

    我为此提交了一个补丁,修复在 PHP 5.3.7 及更高版本中。请参阅此错误报告以获取更多信息http://bugs.php.net/54167

    从 PHP 5.3.7 开始,它会将 uniqueidentifier 作为字符串返回,该字符串适用于 Doctrine 1 和 2。

    在我的例子中,我还需要在 freetds.conf 中指定 tds 版本,以正确接收作为字符串的 uniqueidentifier 值。适合我的 tds 版本(可能特定于我正在与之通信的 SQL 服务器版本)是“tds version = 7.0”

    【讨论】:

    • 史诗般的发现,我的朋友。不幸的是,我选择不使用 Doctrine 的原因有很多,与其他原因相比,这是次要的。
    【解决方案2】:

    PHP 有 2 个修复,Bug #54167 解决了 dblib 的 NULL 问题。不幸的是,当它被合并到 PHP 中时,另一个错误导致了另一个唯一标识符问题,从而破坏了它们。基本上,它们会丢失较低的位(用 E3407588-2B77-0000-0200-000000000000 之类的零填充它们)。 There is a bug fix,但要到 PHP 5.4 才会出现。

    一般的解决方案是将 uniqueidentifer 转换为字符串,但 Doctrine 不处理这个问题。 Doctrine 的一个简单补丁包括将列定义从string(36) 更改为guid,然后让 Doctrine 在 Query.php 文件中为您执行转换。一个示例是:

    // In the schema file
    columns:
      userid:
        type: guid
        fixed: false
        unsigned: false
        notnull: false
        primary: true
        autoincrement: false
    
    // Which generates this in the base model
    $this->hasColumn('userid', 'guid', null, array(
             'type' => 'guid',
             'fixed' => 0,
             'unsigned' => false,
             'notnull' => false,
             'primary' => true,
             'autoincrement' => false,
    ));
    
    // Only after you change this in Doctrine/DataDict/Mssql.php on line 192-194
    case 'uniqueidentifier':
        $type[] = 'guid'; // changed from 'string'
        $length = 36;
    
    // Then to use the new guid datatype, edit Doctrine/Query.php starting on line 487
    foreach ($fields as $fieldName) {
            $columnName = $table->getColumnName($fieldName);
            if (($owner = $table->getColumnOwner($columnName)) !== null &&
                    $owner !== $table->getComponentName()) {
    
                $parent = $this->_conn->getTable($owner);
                $columnName = $parent->getColumnName($fieldName);
                $parentAlias = $this->getSqlTableAlias($componentAlias . '.' . $parent->getComponentName());
                $sql[] = $this->_conn->quoteIdentifier($parentAlias) . '.' . $this->_conn->quoteIdentifier($columnName)
                       . ' AS '
                       . $this->_conn->quoteIdentifier($tableAlias . '__' . $columnName);
            } else {
                /* This new code will get the column definition, look for guid, then cast the column as a string to work around PHP bug 60033.  Everything above this line is unchanged */
                $columnName = $table->getColumnName($fieldName);
    
                $columnDefinition = $table->getColumnDefinition($columnName);
    
                if ($columnDefinition['type'] == 'guid') {
                    $sql[] = 'CAST(' . $this->_conn->quoteIdentifier($tableAlias) . '.' . $this->_conn->quoteIdentifier($columnName) . ' as VARCHAR(36))'
                       . ' AS '
                       . $this->_conn->quoteIdentifier($tableAlias . '__' . $columnName);
    
                } else {
                        // this block is unchanged from the original
                    $sql[] = $this->_conn->quoteIdentifier($tableAlias) . '.' . $this->_conn->quoteIdentifier($columnName)
                       . ' AS '
                       . $this->_conn->quoteIdentifier($tableAlias . '__' . $columnName);
                }
            }
        }
    

    我不确定您是否需要在 IF 语句的第一部分添加与上面相同的代码,但我添加了此代码,现在我的所有唯一标识符都正确返回(下部不是零,如 E3407588- 2B77-0000-0276-3D9E8DE868D6)。也许 Doctrine 中的人会添加这个补丁,因为 Doctrine 对于任何 PHP

    而且我知道不建议手动编辑 Doctrine 代码,但这是在我尝试从源代码运行 PHP 5.4 beta2 并花费数小时试图让更新的 sqlsrv 驱动程序在 Doctrine 1.2 中工作之后。此外,这些代码行比使用旧的 mssql_query 代码重写我的所有查询要容易得多。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-27
      • 1970-01-01
      • 2017-05-06
      • 2010-11-26
      • 2010-10-15
      • 2016-01-20
      相关资源
      最近更新 更多