I have a module which is misbehaving. An EFQ is returing unexpected results, but I can't see why just by looking at the code. Is there a dpq() equivalent for EFQs? Other ways of debugging them?
-
Similar question: drupal.stackexchange.com/questions/33473/…. Can you cast the query object to a string to inspect it to see if the SQL gives any clues?– Clive ♦Commented Jul 10, 2012 at 8:43
-
1Great suggestions, however: Recoverable fatal error: Object of class EntityFieldQuery could not be converted to string :(– LetharionCommented Jul 10, 2012 at 8:50
6 Answers
It's a wee bit of a hack, but you could add a tag to any EntityFieldQuery
you're interested in printing the query for, then implement hook_query_alter()
to intercept it when it's a standard SelectQuery
, then cast it to string for debugging:
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();
It's a bit of a hack but does the trick. The output for the above is:
SELECT node.nid AS entity_id, node.vid AS revision_id, node.type AS bundle, :entity_type
AS entity_type
FROM {node} node
Presumably this will also only work when using MySQL as the field storage system.
-
Sounds great in theory, but what about the comments on the question? EFQ doesn't implement __toString()? Commented Jul 20, 2012 at 11:19
-
4By the time it gets to
hook_query_alter()
the query isn't anEntityFieldQuery
any more, it's been converted down to a standarddb_select()
, so__tostring()
works great :) Since working this out I've been using it quite a lot and it works pretty well– Clive ♦Commented Jul 20, 2012 at 12:11 -
Confirmed that casting to string works once the query gets to
hook_query_alter()
. Commented Aug 27, 2012 at 21:09 -
To see the query argumentos (":entity_type" in the above example) you can use dpm($query->arguments());– sanzanteCommented Nov 23, 2014 at 14:09
Rather than rolling your own hook_query_alter() you can let Devel module do the heavy lifting for you by adding the debug
tag:
$q = new EntityFieldQuery;
$q->entityCondition('entity_type', 'node');
->addTag('debug')
->execute();
This will print the query to screen, just like dpq()
would.
Adding to the @Clive answer, which generally prints the query with the placeholder not along with the value. To print the value with the query use the following code under the 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();
It is not good practice to install a module for the few lines of code. That is why I opted for the aforementioned solution.
If you download the dev version of Nice DPQ (or anything => 1.1), you can simply do:
$user_query = new EntityFieldQuery();
$user_query->entityCondition('entity_type','user');
$user_query->addTag('nicedpq');
$user_result = $user_query->execute();
and you will get the query dpm'ed nicely :). The important part in the code above is addTag('nicedpq') - that triggers the dpm()
.
-
nice alternate workaround to devel. Couldn't find that module directly over DO because they removed related module block which was there earliar. Commented Oct 13, 2015 at 8:44
You can try to debug it via XDebug. Once installed, do xdebug_start_trace()
before the code, and xdebug_stop_trace()
after that, then you'll have clear trace log what was executed and where.
Also you can enable query logger in MySQL configuration.
The other method is to use strace/truss/dtruss like debuggers.
Example using dtruss:
all queries
sudo dtruss -t read -n mysqld
specific queries
sudo dtruss -t read -n mysqld 2>&1 | grep SPECIFIC_TEXT
Note that dtruss
is just a script which uses DTrace, so you may consider a direct implementation of PHP DTrace static probes or DTracing MySQL by writing your own script.
Read more: Advanced debugging of Drupal core using the command line (strace & tcpdump)
Add this function to your module. Then, add the tag debug
to any EFQ. Requires Devel module to be enabled in order to print the query.
/**
* 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);
}
}