DebugHelper.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. namespace loyalsoft;
  3. /**
  4. * 调试辅助脚本,目前主要集中在输出功能.
  5. * @version
  6. * 2.0.1 添加检查PHP version和extensions的方法. --gwang 2019年8月16日 15:15:48
  7. * 1.0.0 Created at 2016-7-1. by --gwang
  8. * @author gwang (mail@wanggangzero.cn)
  9. * @copyright © 2016-7-1, SJZ LoyalSoft Corporation & gwang. All rights reserved.
  10. */
  11. class DebugHelper {
  12. /**
  13. * @return bool 调试输出是否开启
  14. */
  15. private static function isDebugging() {
  16. return defined('DEBUGING') && DEBUGING; # 线上版屏蔽输出
  17. }
  18. /**
  19. * 尝试从array中取出一个命名变量, Ps.可以取消5.3中的Notice
  20. * @param array $arr
  21. * @param string $strFieldName
  22. * @return mixed
  23. */
  24. private static function arr_get($arr, $strFieldName) {
  25. if (isset($arr[$strFieldName])) {
  26. return $arr[$strFieldName];
  27. }
  28. return null;
  29. }
  30. //
  31. // <editor-fold defaultstate="collapsed" desc="assert">
  32. /**
  33. * 逻辑断言,不受系统断言状态影响,可以用于生产环境的简单判断,比如:参数非法,参数缺失等
  34. * @param bool $condition
  35. * @param int/string $err 如果是int值,则当作Errcode处理,否则当作字符串处理
  36. */
  37. static function assert($condition, $err) {
  38. if (!$condition) { # 断言失败
  39. if (is_int($err)) { # err是int值,则按照错误码查找错误提示信息
  40. $msg = "";
  41. $errMsg = GameConfig::errmsg_getItem($err);
  42. if (isset($errMsg)) {
  43. $msg = $errMsg->msg;
  44. }
  45. CLog::err("断言失败!", $msg);
  46. Err($err, $msg);
  47. } else { # 不是int值,则当做普通错误信息来处理
  48. CLog::err("断言失败!", $err);
  49. Err(ErrCode::msg_assert, $err);
  50. }
  51. }
  52. }
  53. /**
  54. * 接管系统的断言失败处理函数(调试用,若要检查参数是否完整,请用Resp::assert())
  55. * 注意:方法内部依赖于GAME_ONLINE标志,若为内网调试则打开断言,
  56. * 若为线上环境则关闭断言(提升安全性和部分性能)
  57. */
  58. static function cover_assert_handler() {
  59. assert_options(ASSERT_ACTIVE, true); # 设置断言标志
  60. assert_options(ASSERT_BAIL, true);
  61. assert_options(ASSERT_WARNING, false);
  62. assert_options(ASSERT_CALLBACK, array('DebugHelper', 'my_assert_handler')); # 设置回调函数
  63. }
  64. /**
  65. * 断言处理函数
  66. * @param string $file
  67. * @param int $line
  68. * @param string $code
  69. * @param string $desc
  70. */
  71. private static function my_assert_handler($file, $line, $code, $desc) {
  72. $msg = "<hr>Assertion Failed:
  73. File '$file'<br />
  74. Line '$line'<br />
  75. Code '$code'<br />
  76. Desc '{$desc}'<br />
  77. <hr />";
  78. Err(Err::err_assert, $msg); # 给客户端返回值
  79. // trigger_error($msg, E_USER_ERROR); # 抛出一个err
  80. }
  81. // </editor-fold>
  82. //
  83. /**
  84. * 浏览器打印调试信息
  85. * @param mixed $msg 对象或数组将会被序列化为json串
  86. */
  87. public static function debug($msg) {
  88. if (self::isDebugging()) {
  89. if (is_array($msg) || is_object($msg)) {
  90. $msg = json_encode($msg);
  91. }
  92. echoLine('[' . TimeUtil::dtCurrent() . ']| ' . $msg);
  93. }
  94. }
  95. /**
  96. * var_dump输出变量,统一入口的话, 上线的时候通过统一变量关闭,防止漏删除的意外输出.
  97. * @param mixed $obj
  98. */
  99. public static function var_dump($obj) {
  100. if (!self::isDebugging()) {
  101. return;
  102. }
  103. $pos = self::get_call_stack();
  104. $stack = explode('<br/>', $pos);
  105. $n = 3 > count($stack) ? count($stack) : 3;
  106. for ($i = 0; $i < $n; $i++) {
  107. echoLine($stack[$i]);
  108. }
  109. echoLine(); # 换个行
  110. var_dump($obj);
  111. }
  112. /**
  113. * 浏览器输出调用堆栈
  114. * @return void
  115. */
  116. public static function print_stack_trace() {
  117. /* * * * *
  118. * 因为debug_print_backtrace()格式不太易读,自己调整下输出样式
  119. * * * */
  120. $html = self::get_call_stack();
  121. self::debug($html);
  122. }
  123. /**
  124. * 获得调用堆栈
  125. * @param int $nestedLevelNum 调用的嵌套层次,default is 1
  126. * @return string formated string
  127. */
  128. static public function get_call_stack($nestedLevelNum = 1, $n = 3, $printArg = false) {
  129. $outHtml = "";
  130. $arr = debug_backtrace();
  131. // var_dump($arr);
  132. $array = array_slice($arr, $nestedLevelNum, $n); # 移除get_call_stack函数自身
  133. // var_dump($array);
  134. foreach ($array as $row) {
  135. $outHtml .= "\t" . CommUtil::str2UTF8(self::arr_get($row, 'file')) . # windows下路径(gb2312)转码
  136. ' method: ' . self::arr_get($row, 'class') . self::arr_get($row, 'type') . self::arr_get($row, 'function') # func
  137. . '(' . ($printArg ? JsonUtil::encode(self::arr_get($row, 'args')) : "") . ')' # 参数
  138. . ', row: ' . self::arr_get($row, 'line') # line
  139. . ";<br/>" . PHP_EOL;
  140. }
  141. return $outHtml;
  142. }
  143. /**
  144. * 浏览器弹窗提示
  145. * @param string $msg
  146. */
  147. public static function alert($msg) {
  148. if (self::isDebugging()) {
  149. echo "<Script language=\"javascript\">alert(\"" . $msg . "\");</Script>";
  150. }
  151. }
  152. }