Doctrine SQL Server在从数据库中检索uniqueidentifier时未将其转换为char或nvarchar。

3
当我从数据库中检索到一个具有“uniqueidentifier”类型列的记录时,Doctrine会将其填充为“null”,而不是来自数据库的唯一ID。
经过一些研究和测试,发现这是PDO/dblib驱动程序的问题。直接通过PDO查询时,唯一ID的位置返回null。
参考http://trac.doctrine-project.org/ticket/1096,其中有关于此问题的说明,但是它在11个月前被更新,没有解决方案的评论。
http://bugs.php.net/bug.php?id=24752&edit=1所述,一个解决方法是将该列转换为char。然而,Doctrine似乎没有在生成模型之外公开本机字段类型,这使得在构建SQL查询时难以检测uniqueidentifier类型并在内部进行转换。
是否有人找到了解决此问题的方法?
2个回答

2
我为此提交了一个补丁,修复在PHP 5.3.7及以后版本中。有关详细信息,请参见此错误报告
从PHP 5.3.7开始,它将返回唯一标识符作为字符串,这将与Doctrine 1和2正常工作。
在我的情况下,我还需要在freetds.conf中指定tds版本,以正确接收唯一标识符值作为字符串。对我有效的tds版本(可能特定于我正在通信的SQL Server版本)为“tds version = 7.0”。

太棒了,我的朋友。不幸的是,出于许多原因,我选择不使用Doctrine,这只是其中一个较小的原因。 - Tres

1

PHP 有两个修复程序,Bug #54167 解决了 dblib 中的 NULL 问题。不幸的是,当它被合并到 PHP 中时,另一个 bug 导致了唯一标识符的另一个问题,使它们损坏。基本上,它们会失去较低的位(用零填充,如 E3407588-2B77-0000-0200-000000000000)。有一个 bug 修复程序,但它要等到 PHP 5.4 才能发布。

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

// 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<5.4中使用SQL Server的唯一标识符都是无用的。

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

希望这可以帮助。


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