当我从具有“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所述,解决这个问题的方法是将列转换为char。但是,似乎Doctrine在生成模型之外暴露了本机字段类型,这使得在构建SQL查询时检测uniqueidentifier类型并在内部转换它们有点困难。
有没有人为此找到解决方法?
答案 0 :(得分:2)
我为此提交了一个补丁,修复版是在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”
答案 1 :(得分:1)
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< 5.4都没有SQL Server的唯一标识符。
我知道不建议手动编辑Doctrine代码,但这是在我尝试从源代码运行PHP 5.4 beta2并花费数小时试图让新的sqlsrv驱动程序在Doctrine 1.2中运行之后。此外,这些代码行比使用旧的mssql_query代码重写所有查询容易得多。
希望这有帮助。