DQL to Raw SQL

Я довольно давно работаю с Doctrine ORM, и очень часто при отладке необходимо посмотреть, какой именно SQL запрос получается из DQL запроса. Для этого раньше я использовал $dql->getSqlQuery() вместе с $dql->getParams(). Первая команда отображает SQL-запрос плейсхолдерами (“?”) вместо переменных, а вторая собственно отображает массив переменных. Приходится смотреть туда-сюда, чтобы сопоставить их. Ладно если запрос маленький, а если большой – то это быстро утомляет.Немного покопавшись в коде, я нашел решение, которое хочу вам показать. Единственное требование, это наличие своего класса запроса. У нас он называется DoctrineExtra_Query, он является наследником Doctrine_Query. Также я сделал небольшие корректировки в других классах (которые тоже отнаследовал), чтобы DoctrineExtra_Query генерировался по умолчанию вместо встроенного в ответ на вызов $connection -> getQueryObject(). Пока писать не буду, но если ко-мунибудь будет интересно – спрашивайте в комментах – отвечу. Итак, собственно в классе DoctrineExtra_Query добавляем новую функцию getRawSql(). Вот её текст:

Как видите, ничего сложного нет, зато теперь отладка запрсоов будет на порядок удобнее.

10 Comments

  1. Случайно не знаете как можно посмотреть код который будет выполнен при save();

    1. Мой метод вызывается у класса DoctrineExtra_Query, который наследуется от Doctrine_Query. Вызов модели Doctrine_Record -> save() вызывает метод $conn->unitOfWork->saveGraph($this) затем вызывается один из следующих методов:

      $isValid = $this->replace($record);
      $isValid = $this->insert($record
      $isValid = $this->update($record);

      которые являются прокси-методами для объекта Connection.
      Внутри вы найдете такой код:

      $sql = ‘UPDATE ‘ . $this->quoteIdentifier($table->getTableName())
      . ‘ SET ‘ . implode(‘, ‘, $set)
      . ‘ WHERE ‘ . implode(‘ = ? AND ‘, $this->quoteMultipleIdentifier($table->getIdentifierColumnNames()))
      . ‘ = ?’;

      Это значит, что операция сохранения записи происходит без участия объекта Doctrine_Query, а значит мой метод неприменим.
      Но вы можете отнаследовать класс Doctrine_Connection и внедрить похожий метод туда.
      Тогда вы сможете смотреть, какие сырые запросы пойдут в базу при вызове $model->save().

  2. подключить я так понял надо так:
    создаем класс и в нем метод getRawSql()
    class DoctrineExtra_Query extends Doctrine_Query
    {
    public function getRawSql()
    {…}
    }
    и вместо Doctrine_Query::create()->from(‘User’)->getSqlQuery();
    уже используем
    DoctrineExtra_Query::create()->from(‘User’)->getRawSql();

    1. Да можно так. И лучше ещё сразу переназначить DoctrineExtra_Query вместо встроенного класса Doctrine_Query вот так:

      $conn->setAttribute(Doctrine_Core::ATTR_QUERY_CLASS, ‘DoctrineExtra_Query’);
      где $conn – Doctrine_Connection

      1. Я в классе Doctrine_Query добавил ваш getRawSql() и теперь можно использовать оба на выбор 🙂

        1. Отлично! А Doctrine у вас случаем не через svn-externals подключен. А то при апдейте ваши изменения могут затареться. Да и вообще не рекомендуется изменять сторонние беблиотеки, а то и рпавда обновитесь, и не заметите, как перестанет работать.

Leave a Comment