Imprimer la requête construite avec db_select ()

61

Je veux imprimer la requête qui est construite en utilisant db_select () de manière programmatique. Existe-t-il une fonction API fournie par Drupal Abstraction Layer?
Il est similaire à la sortie de requête dans Views, mais je souhaite l’imprimer à partir de mon module personnalisé à des fins de débogage.

Sithu
la source

Réponses:

67

SelectQueryimplémente SelectQuery::__toString(), qui est appelée dans les contextes où une chaîne est requise.

Considérons le code suivant.

global $theme_key;

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

print $query;

Sa sortie est la suivante.

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

Pour obtenir le tableau des arguments utilisés pour la requête, vous pouvez appeler SelectQuery::arguments().

Le code suivant imprime la requête et ses arguments à l'aide des fonctions fournies par le module Devel.

global $theme_key;

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

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

capture d'écran

Le module Devel n'est cependant pas nécessaire et vous pouvez drupal_set_message()afficher le résultat. Par exemple, vous pouvez utiliser la fonction suivante pour obtenir une chaîne avec les espaces réservés remplacés par leurs valeurs réelles.

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;
}

L'exemple de code précédent que j'ai montré deviendrait le suivant.

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;
}

Notez que SelectQuery::arguments()renvoie le tableau d'arguments de la requête que si elle est appelée après SelectQuery::__toString(), SelectQuery::compile()ou SelectQuery::execute(); sinon, SelectQuery::arguments()retourne NULL.

Vous pouvez utiliser une fonction similaire à la suivante pour obtenir la requête de chaîne, les espaces réservés étant remplacés par les arguments.

kiamlaluno
la source
1
Je pense qu'une fonction comme _get_query_string()aurait dû faire partie de l' SelectQueryinterface.
Dashohoxha
46

Vous pouvez utiliser dpq () pour afficher la requête et dpr () pour afficher le résultat.

  $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.
umesh
la source
1
Notez que cela nécessite l'installation du module Devel. Si vous utilisez Devel (j'adore ça), c'est le moyen le plus simple.
joe_flash
2
dpq () Où as-tu été toute ma vie!
Lomax
Ne semble pas fonctionner dans un try catchbloc lorsque la requête échoue. Donc pas utile dans mon cas si je ne peux pas déboguer la requête cassée.
Kiee
19

Une autre option est:

global $theme_key;

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

print strtr((string) $query, $query->arguments());
vijaycs85
la source
2
Court et concis en effet.
Dashohoxha
2
Aucun module de ballonnement / tiers requis. De plus, cela fonctionne sur les requêtes qui n'ont pas été exécutées. Vous pouvez donc imprimer une requête qui échoue et donne une erreur. dpqCela ne semble pas le permettre, même dans un try / catch.
Kiee
1
Cela devrait être la bonne réponse.
albertski
8

Les réponses ci-dessus sont utiles lorsque Devel est installé et configuré.

La meilleure façon d’imprimer la requête sans utiliser Devel est la suivante.

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

Nous pouvons utiliser l'une des méthodes ci-dessus pour imprimer la requête.

KiranD
la source
4

J'ai une bonne solution que vous pouvez copier / coller votre chaîne de requête directement dans la section "SQL" de Phpmyadmin et déboguer votre requête (j'utilise souvent cette méthode lorsque j'ai des difficultés avec la requête)

$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);

J'espère que cela sera utile pour les autres gars.

Yusef Mohamadi
la source