Déboguer EntityFieldQuery?

27

J'ai un module qui se comporte mal. Un EFQ retient des résultats inattendus, mais je ne vois pas pourquoi simplement en regardant le code. Existe-t-il un équivalent dpq () pour les EFQ? D'autres façons de les déboguer?

Létharion
la source
Question similaire: drupal.stackexchange.com/questions/33473/… . Pouvez-vous convertir l'objet de requête en une chaîne pour l'inspecter pour voir si le SQL donne des indices?
Clive
1
Excellentes suggestions, cependant: erreur fatale récupérable: l'objet de la classe EntityFieldQuery n'a pas pu être converti en chaîne :(
Letharion

Réponses:

36

C'est un peu un hack, mais vous pouvez ajouter une balise à toutes celles pour lesquelles EntityFieldQueryvous souhaitez imprimer la requête, puis l'implémenter hook_query_alter()pour l'intercepter quand c'est une norme SelectQuery, puis la convertir en chaîne pour le débogage:

function MYMODULE_query_alter($query) {
  if ($query->hasTag('efq_debug')) {
    dpm((string)$query);
  }
}

$q = new EntityFieldQuery;
$q->entityCondition('entity_type', 'node')
  ->addTag('efq_debug')
  ->execute();

C'est un peu un hack mais ça fait l'affaire. La sortie de ce qui précède est:

SELECT node.nid AS entity_id, node.vid AS revision_id, node.type AS bundle, :entity_type     
AS entity_type
FROM {node} node

Vraisemblablement, cela ne fonctionnera que lorsque vous utiliserez MySQL comme système de stockage sur le terrain.

Clive
la source
Sonne bien en théorie, mais qu'en est-il des commentaires sur la question? EFQ n'implémente pas __toString ()?
Letharion
4
Au moment où il arrive à hook_query_alter()la requête n'est EntityFieldQueryplus, il a été converti en un standard db_select(), donc ça __tostring()marche très bien :) Depuis que ça marche, je l'ai beaucoup utilisé et ça marche plutôt bien
Clive
Confirmé que la conversion en chaîne fonctionne une fois la requête terminée hook_query_alter().
jhedstrom
Pour voir les arguments de la requête (": type_entité" dans l'exemple ci-dessus), vous pouvez utiliser dpm ($ query-> arguments ());
sanzante
13

Plutôt que de rouler votre propre hook_query_alter (), vous pouvez laisser le module Devel faire le gros du travail pour vous en ajoutant la debugbalise:

$q = new EntityFieldQuery;
$q->entityCondition('entity_type', 'node');
  ->addTag('debug')
  ->execute();

Cela imprimera la requête à l'écran, comme vous le dpq()feriez.

Dalin
la source
4

Ajout à la réponse @Clive, qui imprime généralement la requête avec l'espace réservé et non avec la valeur. Pour imprimer la valeur avec la requête, utilisez le code suivant sous hook_query_alter.

function hook_query_alter($query) {
  if ($query->hasTag('debug')) {
    $sql = (string)$query;
    $connection = Database::getConnection();
    foreach ((array) $query->arguments() as $key => $val) {
      $quoted[$key] = $connection->quote($val);
    }
    $sql = strtr($sql, $quoted);
    dpm($sql);
  }
}


$q = new EntityFieldQuery;
$q->entityCondition('entity_type', 'node');
  ->addTag('debug');
  ->execute();

Il n'est pas recommandé d'installer un module pour les quelques lignes de code. C'est pourquoi j'ai opté pour la solution susmentionnée.

Sukhjinder Singh
la source
2

Si vous téléchargez la version dev de Nice DPQ (ou n'importe quoi => 1.1), vous pouvez simplement faire:

$user_query = new EntityFieldQuery();
$user_query->entityCondition('entity_type','user');
$user_query->addTag('nicedpq');
$user_result = $user_query->execute();

et vous obtiendrez bien la requête dpm'ed :). La partie importante dans le code ci-dessus est addTag ('nicedpq') - qui déclenche le dpm().

mojzis
la source
belle solution alternative à développer. Impossible de trouver ce module directement sur DO car ils ont supprimé le bloc de module connexe qui était là auparavant.
kiranking
1

Vous pouvez essayer de le déboguer via XDebug . Une fois installé, faites xdebug_start_trace()avant le code, et xdebug_stop_trace()après cela, vous aurez un journal de trace clair ce qui a été exécuté et où.

Vous pouvez également activer l'enregistreur de requêtes dans la configuration MySQL.

L'autre méthode consiste à utiliser strace / truss / dtruss comme des débogueurs.

Exemple utilisant dtruss:

  • toutes les requêtes

    sudo dtruss -t read -n mysqld
  • requêtes spécifiques

    sudo dtruss -t read -n mysqld 2>&1 | grep SPECIFIC_TEXT

Notez que ce dtrussn'est qu'un script qui utilise DTrace, vous pouvez donc envisager une implémentation directe des sondes statiques PHP DTrace ou DTracing MySQL en écrivant votre propre script.

En savoir plus: Débogage avancé du noyau Drupal à l'aide de la ligne de commande (strace & tcpdump)

kenorb
la source
0

Ajoutez cette fonction à votre module. Ensuite, ajoutez la balise debugà n'importe quel EFQ. Nécessite que le module Devel soit activé pour imprimer la requête.

/**
 * Implements hook_query_TAG_alter().
 *
 * Add the tag 'debug' to any EFQ and this will print the query to the messages.
 *
 * @param \QueryAlterableInterface $query
 */
function MYMODULE_query_debug_alter(QueryAlterableInterface $query) {
  if (function_exists('dpq') && !$query->hasTag('debug-semaphore')) {
    $query->addTag('debug-semaphore');
    dpq($query);
  }
}
ClavierCowboy
la source