3

「uniqueidentifier」タイプの列を持つデータベースからレコードを取得すると、Doctrineはデータベースからの一意のIDではなく「null」でレコードを埋めます。

いくつかの調査とテストにより、これはPDO/dblibドライバーの問題に帰着しました。PDOを介して直接クエリを実行すると、一意のIDの代わりにnullが返されます。

参考までに、http://trac.doctrine-project.org/ticket/1096にこれについて少し触れていますが、11か月前に更新され、解決のためのコメントはありません。

これを回避する方法は、http://bugs.php.net/bug.php?id = 24752&edit = 1で説明されているように、列を文字としてキャストすることです。ただし、Doctrineがモデルの生成以外にネイティブフィールドタイプを公開しているようには見えないため、SQLクエリを構築するときにuniqueidentifierタイプを検出して内部でキャストするのが少し難しくなります。

誰かがこれの回避策を見つけましたか?

4

2 に答える 2

2

このためのパッチを提出しました。修正はPHP5.3.7以降にあります。詳細については、このバグレポートを参照してくださいhttp://bugs.php.net/54167

PHP 5.3.7以降、Doctrine1および2で正常に機能する文字列としてuniqueidentifierを返します。

私の場合、uniqueidentifier値を文字列として適切に受け取るために、freetds.confでtdsバージョンを指定する必要もありました。私のために働いたtdsバージョン(おそらく私が通信しているSQLサーバーバージョンに固有です)は「tdsバージョン=7.0」です

于 2011-03-19T07:34:55.547 に答える
1

PHPには2つの修正があり、バグ#54167はdblibのNULL問題を解決します。残念ながら、PHPにマージされたとき、別のバグが原因で一意の識別子に別の問題が発生し、それらが破損していました。基本的に、下位ビットは失われます(E3407588-2B77-0000-0200-000000000000のようにゼロで埋めます)。 バグ修正がありますが、PHP5.4まで出てきません。

一般的な解決策は、uniqueidentiferを文字列としてキャストすることですが、Doctrineはこれを処理しません。Doctrineの簡単なパッチでは、列の定義をaからaに変更してから、string(36)Doctrineguidに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は、PHP<5.4のどのバージョンでもSQLServerの一意の識別子では役に立たないため、Doctrineの担当者がこのパッチを追加する可能性があります。

また、Doctrineコードを手動で編集することはお勧めできませんが、これは、ソースからPHP 5.4 beta2を実行し、Doctrine1.2で新しいsqlsrvドライバーを動作させるために何時間も費やした後のことです。さらに、これらのコード行は、古いmssql_queryコードを使用してすべてのクエリを書き直すよりもはるかに簡単です。

お役に立てれば。

于 2011-11-09T18:17:08.523 に答える