3

当我从数据库中检索具有“uniqueidentifier”类型列的记录时,Doctrine使用“null”而不是唯一标识符填充它来自数据库。Doctrine SQL Server uniqueidentifier在从数据库检索时没有转换为char或nvarchar

一些研究和测试已将此归结为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类型并在内部强制转换它们有点困难。

有没有人找到解决方法?

回答

2

我为此提交了补丁,修复程序在PHP 5.3.7及更高版本中。有关进一步信息这个错误报告http://bugs.php.net/54167

自PHP 5.3.7它将返回唯一标识符为字符串,这将很好地工作原则1 & 2.

在我的情况,我还需要指定使用freetds.conf中的tds版本以字符串正确接收uniqueidentifier值。对我来说tds版本(可能特定于我正在与之通信的SQL服务器版本)是“tds version = 7.0”

+0

史诗发现,我的朋友。不幸的是,我选择不使用Doctrine的原因很多,与其他人相比,这是一个小问题。 – Tres 2011-03-20 04:19:02

1

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

一般的解决方案是将uniqueidentifer作为字符串进行投射,但是Doctrine不处理这个问题。一个简单的Doctrine补丁包括将列定义从string(36)更改为​​,然后让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对SQL Server的唯一标识符无任何版本的PHP < 5.4。

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

希望这会有所帮助。

相关问题