DQL to Raw SQL
Я довольно давно работаю с Doctrine ORM, и очень часто при отладке необходимо посмотреть, какой именно SQL запрос получается из DQL запроса. Для этого раньше я использовал $dql->getSqlQuery() вместе с $dql->getParams(). Первая команда отображает SQL-запрос плейсхолдерами (“?”) вместо переменных, а вторая собственно отображает массив переменных. Приходится смотреть туда-сюда, чтобы сопоставить их. Ладно если запрос маленький, а если большой – то это быстро утомляет.Немного покопавшись в коде, я нашел решение, которое хочу вам показать. Единственное требование, это наличие своего класса запроса. У нас он называется DoctrineExtra_Query, он является наследником Doctrine_Query. Также я сделал небольшие корректировки в других классах (которые тоже отнаследовал), чтобы DoctrineExtra_Query генерировался по умолчанию вместо встроенного в ответ на вызов $connection -> getQueryObject(). Пока писать не буду, но если ко-мунибудь будет интересно – спрашивайте в комментах – отвечу. Итак, собственно в классе DoctrineExtra_Query добавляем новую функцию getRawSql(). Вот её текст:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/** * Возвращает сырой SQL-запрос на основе текущего DQL-запроса, * в контексте которого запускается */ public function getRawSql() { $sql = $this->getSqlQuery(); $flattenedParams = array_reverse($this->getFlattenedParams()); // переворачиваем массив, т.к. потом будем использовать array_pop() $value = array_pop($flattenedParams); while(!is_null($value)) { $sql = preg_replace("/\?/", $value, $sql, 1); $value = array_pop($flattenedParams); } return $sql; } |
Как видите, ничего сложного нет, зато теперь отладка запрсоов будет на порядок удобнее.
Случайно не знаете как можно посмотреть код который будет выполнен при save();
А мой метод не подошел?
а как вызывать ваш метод?
save()->getRawSql();
Мой метод вызывается у класса DoctrineExtra_Query, который наследуется от Doctrine_Query. Вызов модели Doctrine_Record -> save() вызывает метод $conn->unitOfWork->saveGraph($this) затем вызывается один из следующих методов:
которые являются прокси-методами для объекта Connection.
Внутри вы найдете такой код:
Это значит, что операция сохранения записи происходит без участия объекта Doctrine_Query, а значит мой метод неприменим.
Но вы можете отнаследовать класс Doctrine_Connection и внедрить похожий метод туда.
Тогда вы сможете смотреть, какие сырые запросы пойдут в базу при вызове $model->save().
спасибо
Пожалуйста, обращайтесь если что)
подключить я так понял надо так:
создаем класс и в нем метод getRawSql()
class DoctrineExtra_Query extends Doctrine_Query
{
public function getRawSql()
{…}
}
и вместо Doctrine_Query::create()->from(‘User’)->getSqlQuery();
уже используем
DoctrineExtra_Query::create()->from(‘User’)->getRawSql();
Да можно так. И лучше ещё сразу переназначить DoctrineExtra_Query вместо встроенного класса Doctrine_Query вот так:
Я в классе Doctrine_Query добавил ваш getRawSql() и теперь можно использовать оба на выбор 🙂
Отлично! А Doctrine у вас случаем не через svn-externals подключен. А то при апдейте ваши изменения могут затареться. Да и вообще не рекомендуется изменять сторонние беблиотеки, а то и рпавда обновитесь, и не заметите, как перестанет работать.