Cuando se trabaja con EntityFieldQuery, db_select y otras formas de abstracción del SQL a veces se quiere acceder a la consulta efectiva SQL que se realiza, normalmente cuando uno está depurando. Los objetos de tipo SelectQuery, InsertQuery, UpdateQuery, etc, implementan el método mágico de PHP __toString(), de forma que basta hacer un casting a string para ver el SQL de la consulta:
$query_object = db_select('users', 'u')->fields('u');
$query_text = (string) $query_object;
El valor de $query_text será:
SELECT u.* FROM {users} u
Sin embargo, EntityFieldQuery no implementa el método __toString(), por lo que hay que usar un truco. EntityFieldQuery, internamente, usa un objeto SelectQuery que sí dispone del método __toString(). Basta con engancharse en el punto adecuado y mostrar la consulta, una vez es ya un objeto SelectQuery. Para ello habrá que hacer dos cosas: marcar la consulta para ser 'depurada' mediante una etiqueta a la query e implementar el hook_query_alter().
Por ejemplo, supongamos que tenemos el siguiente EntityFieldQuery:
$efq = new EntityFieldQuery;
$result = $efq->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'page')
->execute();
Para depurarlo habría que añadirle una etiqueta, por ejemplo 'efq_debug':
$efq = new EntityFieldQuery;
$result = $efq->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'page')
->addTag('efq_debug')
->execute();
E implementar el correspondiente hook:
function mymodule_query_alter($query) {
if ($query->hasTag('efq_debug')) {
dpm((string) $query, 'Consulta');
dpm($query->arguments(), 'Argumentos');
}
}
Como resultado obtenemos para el primer dpm:
SELECT node.nid AS entity_id, node.vid AS revision_id, node.type AS bundle, :entity_type AS entity_type
FROM
{node} node
WHERE (node.type = :db_condition_placeholder_0)
Como puede verse la consulta viene con placeholders. Esta es la razón por la que se incluye el segundo dpm(), con los argumentos de la consulta:
:db_condition_placeholder_0 (String, 4 characters ) page
:entity_type (String, 4 characters ) node
Obviamente esto solo debería estar activado en desarrollo. Me hubiese gustado haber pensado esta forma de depurar el EntityFieldQuery pero antes de hacerlo busqué y encontré una respuesta de Clive, el Chuck Norris de Drupal Answers.
Actualización
Como comentan en la propia pregunta ahora el módulo devel incluye este truco: basta con añadir la etiqueta debug:
$q = new EntityFieldQuery;
$q->entityCondition('entity_type', 'node')
->addTag('debug')
->execute();