错误信息

Deprecated function: The each() function is deprecated. This message will be suppressed on further calls 在 menu_set_active_trail() (行 2405/data/itxueku/includes/menu.inc).

Drupal实用本地调试函数

浏览:107
drupal开发中,调试是必不可少的,可以帮助我们找到bug,或者性能优化、或者改善用户体验等等。而关于调试的话题,本站已经有过几篇文章专门论述了,大家可以参考如下几篇:

Drupal调试之Devel模块使用技巧
Drupal/PHP性能分析工具之xDebug


本文的重点不是向大家推荐其他需要安装的工具,而是一段我认为非常有用的调试代码,有了这段代码,可以很清晰的了解一些debug信息。





define('DEBUG_INIT', 0x0001);define('DEBUG_STOP', 0x0002);define('DEBUG_SHOW', 0x0004 | DEBUG_STOP);define('DEBUG_RETURN', 0x0008 | DEBUG_STOP); /**
 * Debug helper for time consuming, check real SQL to investigate bug or performance issue.
 *
 * @global type $conf
 * @global type $queries
 * @staticvar array $timers
 * @staticvar array $run_times
 * @staticvar array $queries_timer
 * @staticvar array $last_info
 * @staticvar null $old_values
 * @param system $timer Name your debug code
 * @param type $mode could be DEBUG_SHOW or DEBUG_RETURN generally
 * @return type
 * @version 1.0
 * @author Richard Yu (vipzhicheng#gmail.com)
 */function local_debug($timer = NULL, $mode = DEBUG_INIT) {   if (!isset($timer)) {$timer = __FUNCTION__;
  }   global $conf, $queries;
  static $timers = array();
  static $run_times = array();
  static $queries_timer = array();
  static $last_info = array();   if (!isset($run_times[$timer])) {$run_times[$timer] = 0;
  }   $run_times[$timer]++;   if ($run_times[$timer] == 2 && $mode === DEBUG_INIT) {$mode = DEBUG_SHOW | DEBUG_STOP;$run_times[$timer] = 0;
  }
  else if ($mode & DEBUG_STOP) {$run_times[$timer] = 0;
  }
  else {$queries = array();timer_start($timer); if (!isset($timers[$timer])) {  $timers[$timer] = array();}
  } 
  static $old_values = NULL;   if (!isset($old_values[$timer])) {$old_values[$timer] = $conf['dev_query'];$conf['dev_query'] = 1;   }
  else if ($mode & DEBUG_SHOW || $mode & DEBUG_RETURN) {$conf['dev_query'] = $old_values[$timer];$old_values = NULL;
  }   $record_info = FALSE;
  foreach ($timers as $key => $value) { if ($key === $timer && $mode & DEBUG_STOP) {  $timers[$key]['read'] = timer_read($key);  timer_stop($key);  $record_info = TRUE;  break;}
  }   foreach ($queries as $key => $query) {$queries[$key][1] = round($queries[$key][1] * 1000, 2);$queries_timer[$timer] += $queries[$key][1]; // Don't show if it is slave queryif (isset($queries[$key][2])) {  unset($queries[$key][2]);}
  }   $info = array('queries' => $queries,'total_timer' => $timers[$timer]['read'],'total_query_timer' => $queries_timer[$timer],'total_process_timer' => ((float)$timers[$timer]['read'] - (float)$queries_timer[$timer]), 'this_timer' => $timers[$timer]['read'] - $last_info[$timer]['total_timer'],'this_query_timer' => $queries_timer[$timer] - $last_info[$timer]['total_query_timer'],'this_process_timer' => ((float)$timers[$timer]['read'] - (float)$queries_timer[$timer] - $last_info[$timer]['total_process_timer'])
  );   $last_info[$timer] = $info;   if ($record_info) {$timers[$timer]['infos'][] = $info;
  }   if ($mode & DEBUG_SHOW) {dpm($info, $timer);
  }
  else if ($mode & DEBUG_RETURN) {return $info;
  }}

这段代码一般可以粘贴到settings.php里,就可以到处运行了。我一般会在本地开发一个不进SVN的local模块,把这个函数放在local模块里。注意,本函数依赖devel模块开启


这个模块的运行结果截图如下:


调试信息


从调试信息的截图,我们可以看到,调试信息里有真正执行的SQL语句,有其执行时间,还有整个代码的执行时间。看调试信息有total_开头的时间,还有this_开头的时间,因为如果给local_debug第一个参数传同样的计时器名字,则时间是会累加的,时间的单位是毫秒。


给调试代码命名的示例代码如下:





local_debug('sql-1');db_query("SELECT 1 FROM {users} LIMIT 1");local_debug('sql-1'); 
local_debug('sql-2');db_query("SELECT 1 FROM {node} LIMIT 1");local_debug('sql-2'); // sql-1的运行总时间会累加local_debug('sql-1');db_query("SELECT 1 FROM {system} LIMIT 1");local_debug('sql-1');

如果是希望将调试信息记录到日志里则:





local_debug('sql-1');db_query("SELECT 1 FROM {node} LIMIT 1");YOUR_LOG_FUNCTION(local_debug('sql-1', DEBUG_RETURN);

注意事项是本函数目前只支持串行的使用,还不支持嵌套


本函数的使用场景:



  1. 想看看一个db_query执行时替换后的SQL语句的原貌




  2. 想看看一个我们自定义函数或者一大段代码里执行了哪些SQL语句




  3. 想看看我们代码的性能如何




  4. 诊断BUG,一般配合devel模块的php在线运行功能




  5. 为记录系统日志提供一定的信息



总之这个函数就是一个助手函数,我相信可以给大家的日常开发帮助带来一些帮助。本函数在以后实际使用中会根据需要再次进行调整,大家有什么好的建议也可以提出来。




top