调试EntityFieldQuery吗?


27

我有一个行为异常的模块。EFQ正在重现意想不到的结果,但是我无法仅通过查看代码来了解原因EFQ是否有dpq()等效项?其他调试方式?


类似的问题:drupal.stackexchange.com/questions/33473/…。您可以将查询对象转换为字符串以检查它以查看SQL是否提供任何线索吗?
克莱夫(Clive)

1
但是,很好的建议是:可恢复的致命错误:EntityFieldQuery类的对象无法转换为字符串:(
Letharion 2012年

Answers:


36

这有点麻烦,但是您可以在想要EntityFieldQuery打印查询的任何对象上添加标签,然后hook_query_alter()在标准情况下实现拦截功能SelectQuery,然后将其转换为字符串以进行调试:

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

这有点hack,但是可以解决问题。上面的输出是:

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

大概这也仅在使用MySQL作为现场存储系统时才有效。


从理论上讲听起来不错,但是对这个问题的评论呢?EFQ不实现__toString()吗?
Letharion 2012年

4
hook_query_alter()查询的时候不再了EntityFieldQuery,它已经转换为标准了db_select(),因此__tostring()效果很好:)自从设计出来以来,我已经使用了很多,而且效果很好
Clive

确认查询到达时可以强制转换为字符串hook_query_alter()
jhedstrom

要查看查询参数(在上例中为“:entity_type”),可以使用dpm($ query-> arguments());。
sanzante 2014年

13

无需滚动自己的hook_query_alter(),您可以通过添加标签让Devel模块为您完成繁重的工作debug

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

就像dpq()将查询打印到屏幕上一样。


4

添加到@Clive答案,通常会使用占位符而不是值来打印查询。要在查询中打印值,请在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();

为几行代码安装模块不是一个好习惯。因此,我选择了上述解决方案。


2

如果下载Nice DPQ的开发版本(或=> 1.1),则只需执行以下操作:

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

并且您将很好地得到查询dpm'ed :)。上面代码中的重要部分是addTag('nicedpq') -触发dpm()


开发好的替代方法。无法直接在DO上找到该模块,因为他们删除了附近的相关模块块。
kiranking

1

您可以尝试通过XDebug对其进行调试。安装后,xdebug_start_trace()在代码之前执行xdebug_stop_trace()此操作,然后在执行之后,您将获得清晰的跟踪日志,其中执行了什么以及在何处执行。

您也可以在MySQL配置中启用查询记录器。

另一种方法是像调试器一样使用strace / truss / dtruss。

使用dtruss的示例:

  • 所有查询

    sudo dtruss -t read -n mysqld
  • 具体查询

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

请注意,这dtruss只是一个使用DTrace的脚本,因此您可以通过编写自己的脚本来考虑直接实现PHP DTrace静态探针DTracing MySQL

阅读更多:使用命令行(strace和tcpdump)对Drupal核心进行高级调试


0

将此功能添加到您的模块。然后,将标签添加debug到任何EFQ。需要启用Devel模块才能打印查询。

/**
 * 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);
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.