Уникальный идентификатор Doctrine для SQL Server не приводится как char или nvarchar при получении из базы данных - PullRequest
3 голосов
/ 04 мая 2010

Когда я получаю запись из базы данных, в которой есть столбец типа «uniqueidentifier», Doctrine заполняет ее «нулевым», а не уникальным идентификатором из базы данных.

Некоторые исследования и тестирование привели это к проблеме с драйвером PDO / dblib. При непосредственном запросе через PDO вместо уникального идентификатора возвращается ноль.

Для справки, http://trac.doctrine -project.org / ticket / 1096 , имеет немного об этом, однако, он был обновлен 11 месяцев назад без комментариев для разрешения.

Способ обойти это, как упомянуто в http://bugs.php.net/bug.php?id=24752&edit=1,, состоит в том, чтобы привести столбец как символ. Тем не менее, похоже, что Doctrine не предоставляет собственный тип поля вне генерирующих моделей, что затрудняет обнаружение типов уникальных идентификаторов и их внутреннее приведение при построении запроса sql.

Кто-нибудь нашел обходной путь для этого?

Ответы [ 2 ]

2 голосов
/ 19 марта 2011

Я представил патч для этого, исправление в PHP 5.3.7 и более поздних версиях. См. Этот отчет об ошибке для получения дополнительной информации http://bugs.php.net/54167

Начиная с PHP 5.3.7, он возвращает уникальный идентификатор в виде строки, которая будет отлично работать с Doctrine 1 и 2.

В моем случае мне также нужно было указать версию tds в freetds.conf, чтобы правильно получить значение uniqueidentifier в виде строки. Версия tds, которая работала для меня (которая, вероятно, специфична для версии сервера SQL, с которой я общаюсь), имеет вид «tds version = 7.0»

1 голос
/ 09 ноября 2011

Есть 2 исправления для PHP, Ошибка # 54167 решает проблему NULL с dblib. К сожалению, когда он был объединен с PHP, другая ошибка вызвала еще одну проблему с уникальными идентификаторами, которая их повредила. По сути, они будут терять младшие биты (заполняя их нулями, такими как E3407588-2B77-0000-0200-000000000000). Есть исправление ошибки , но оно не появится до PHP 5.4.

Общее решение состоит в том, чтобы приводить уникальный идентификатор как строку, но 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 бесполезен с уникальными идентификаторами SQL Server для любой версии PHP <5.4. </p>

И я знаю, что редактирование кода Doctrine вручную не рекомендуется, но это было после того, как я попытался запустить PHP 5.4 beta2 из исходного кода и потратить часы, пытаясь заставить работать более новый драйвер sqlsrv в Doctrine 1.2. Кроме того, эти строки кода намного проще, чем переписать все мои запросы, используя более старый код mssql_query.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...