Распечатать запрос, который построен с использованием db_select ()

61

Я хочу напечатать запрос, который построен с использованием db_select () программным способом. Есть ли какая-либо функция API, предоставляемая Drupal Abstraction Layer?
Это похоже на вывод запроса в представлениях, но я хочу напечатать его из моего пользовательского модуля для целей отладки.

Ситху
источник

Ответы:

67

SelectQueryреализует SelectQuery::__toString(), который вызывается в контекстах, где требуется строка.

Рассмотрим следующий код.

global $theme_key;

$query = db_select('block')
  ->condition('theme', $theme_key)
  ->condition('status', 1)
  ->fields('block');

print $query;

Его вывод следующий.

SELECT block.*
FROM 
{block} block
WHERE  (theme = :db_condition_placeholder_0) AND (status = :db_condition_placeholder_1)

Чтобы получить массив аргументов, используемых для запроса, вы можете позвонить SelectQuery::arguments().

Следующий код печатает запрос и его аргументы, используя функции, доступные из модуля Devel.

global $theme_key;

$query = db_select('block')
  ->condition('theme', $theme_key)
  ->condition('status', 1)
  ->fields('block');

dpm((string) $query);
dpm($query->arguments());

Скриншот

Однако модуль Devel не нужен, и вы можете drupal_set_message()показать вывод. Например, вы можете использовать следующую функцию, чтобы получить строку с заполнителями, замененными их действительными значениями.

function _get_query_string(SelectQueryInterface $query) {
  $string = (string) $query;
  $arguments = $query->arguments();

  if (!empty($arguments) && is_array($arguments)) {
    foreach ($arguments as $placeholder => &$value) {
      if (is_string($value)) {
        $value = "'$value'";
      }
    }

    $string = strtr($string, $arguments);
  }

  return $string;
}

Код предыдущего примера, который я показал, станет следующим.

global $theme_key;

$query = db_select('block')
  ->condition('theme', $theme_key)
  ->condition('status', 1)
  ->fields('block');

drupal_set_message(format_string('Query: %query', array('%query' => _get_query_string($query))));

function _get_query_string(SelectQueryInterface $query) {
  $string = (string) $query;
  $arguments = $query->arguments();

  if (!empty($arguments) && is_array($arguments)) {
    foreach ($arguments as $placeholder => &$value) {
      if (is_string($value)) {
        $value = "'$value'";
      }
    }

    $string = strtr($string, $arguments);
  }

  return $string;
}

Обратите внимание , что SelectQuery::arguments()возвращает массив аргументов запроса только тогда , когда она вызывается после SelectQuery::__toString(), SelectQuery::compile()или SelectQuery::execute(); в противном случае SelectQuery::arguments()возвращается NULL.

Вы можете использовать функцию, подобную следующей, чтобы получить строковый запрос, с заполнителями, замененными аргументами.

киамалуно
источник
1
Я думаю, что подобная функция _get_query_string()должна была быть частью SelectQueryинтерфейса.
Дашохокша
46

Вы можете использовать dpq () для отображения запроса и dpr () для отображения результата.

  $query = db_select('users','u');
  $query->fields('u');
  $query->condition('u.uid', 1042);
  $result = $query->execute()->fetchAll();

  dpq($query); // Display the query. 
  dpr($result); // Display the query result.
Умеш
источник
1
Обратите внимание, что для этого требуется установить модуль Devel. Если вы используете Devel (мне это нравится), это самый простой способ.
joe_flash
2
dpq () где ты был всю мою жизнь!
Ломакс
Не работает в try catchблоке при сбое запроса. Поэтому в моем случае бесполезно, если я не могу отладить неработающий запрос.
Ки
19

Другой вариант:

global $theme_key;

$query = db_select('block')
  ->condition('theme', $theme_key)
  ->condition('status', 1)
  ->fields('block');

print strtr((string) $query, $query->arguments());
vijaycs85
источник
2
Коротко и кратко на самом деле.
Дашохокша
2
Нет раздувать / сторонних модулей не требуется. Кроме того, это работает с запросами, которые не были выполнены, так что вы можете напечатать запрос, который дает сбой и выдает ошибку, dpqкажется, не позволяет этого даже при попытке / перехвате.
Ки
1
Это должен быть правильный ответ.
Альбертски
8

Приведенные выше ответы хороши, если у вас установлен и настроен Devel.

Лучший способ напечатать запрос без Devel, как показано ниже.

$query = db_select('block')
->condition('theme', $theme_key)
->condition('status', 1)
->fields('block');
//One way
echo $query->__toString();
// Second way
echo (string)$query;

Мы можем использовать один из вышеперечисленных способов для печати запроса.

KiranD
источник
4

У меня есть хорошее решение, что вы можете скопировать / вставить строку запроса непосредственно в разделе «SQL» в Phpmyadmin и отладить ваш запрос (я часто использую этот метод, когда я борюсь с запросом)

$querystring=$query->__toString();
$querystring=str_replace("{",'',$querystring);
$querystring=str_replace("}",'',$querystring);
foreach($query->getArguments() as $key=> $item){

    if(!$item) {
        $item = 'NULL';
    }
    $querystring=str_replace($key.')',$item.')',$querystring);
}
dpm($querystring);

Я надеюсь, что это будет полезно для других парней.

Юсеф Мохамади
источник