Errors.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <?php
  2. namespace Qii\Exceptions;
  3. class Errors extends \Exception
  4. {
  5. const VERSION = '1.2';
  6. /**
  7. * 获取两个文件的相对路径
  8. * @param String $cur
  9. * @param String $absp
  10. * @return String
  11. */
  12. public static function getRelatePath($cur, $absp)
  13. {
  14. $cur = str_replace('\\', '/', $cur);
  15. $absp = str_replace('\\', '/', $absp);
  16. $sabsp = explode('/', $absp);
  17. $scur = explode('/', $cur);
  18. $la = count($sabsp) - 1;
  19. $lb = count($scur) - 1;
  20. $l = max($la, $lb);
  21. for ($i = 0; $i <= $l; $i++) {
  22. if ($sabsp[$i] != $scur[$i])
  23. break;
  24. }
  25. $k = $i - 1;
  26. $path = "";
  27. for ($i = 1; $i <= ($lb - $k - 1); $i++)
  28. $path .= "../";
  29. for ($i = $k + 1; $i <= ($la - 1); $i++)
  30. $path .= $sabsp[$i] . "/";
  31. $path .= $sabsp[$la];
  32. return $path;
  33. }
  34. /**
  35. * 显示错误
  36. *
  37. * @param Object $e Exception
  38. */
  39. public static function getError($e)
  40. {
  41. $message = array();
  42. if (isset($_GET['isAjax']) && $_GET['isAjax'] == 1) {
  43. $code = $e->getCode();
  44. if ($code == 0) $code = 1;
  45. echo json_encode(array('code' => $code, 'line' => $e->getFile() . ' line :' . $e->getLine(), 'msg' => strip_tags($e->getMessage())), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
  46. return;
  47. }
  48. $message[] = (IS_CLI ? QII_EOL : '') . \Qii::i('Error file', self::getRelatePath($_SERVER['SCRIPT_FILENAME'], $e->getFile())) . (IS_CLI ? QII_EOL : '');
  49. $message[] = \Qii::i('Error code', $e->getCode()) . (IS_CLI ? QII_EOL : '');
  50. $message[] = \Qii::i('Error description', $e->getMessage()) . (IS_CLI ? QII_EOL : '');
  51. $message[] = \Qii::i('Error line', $e->getLine() . ' on ' . self::getLineMessage($e->getFile(), $e->getLine())) . (IS_CLI ? QII_EOL : '');
  52. $traceString = \Qii::i('Trace as below') . QII_EOL;
  53. $traces = explode("\n", $e->getTraceAsString());
  54. foreach ($traces AS $trance) {
  55. $traceString .= str_repeat(QII_SPACE, 4) . $trance . QII_EOL;
  56. }
  57. $message[] = $traceString;
  58. if (\Qii::getInstance()->logerWriter != null) {
  59. $message[] = 'Source URL:' . \Qii::getInstance()->request->url->getCurrentURL();
  60. $message[] = 'Referer URL:' . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : \Qii::getInstance()->request->url->getCurrentURL());
  61. \Qii::getInstance()->logerWriter->writeLog($message);
  62. }
  63. $appConfigure = \Qii::appConfigure();
  64. $env = \Qii\Config\Register::get(\Qii\Config\Consts::APP_ENVIRON, 'dev');
  65. if ($env == 'product' || ($appConfigure['errorPage'] && (isset($appConfigure['debug']) && $appConfigure['debug'] == 0))) {
  66. list($controller, $action) = explode(':', $appConfigure['errorPage']);
  67. $controllerCls = $controller;
  68. if(substr($controller, 0, 1) != '\\') {
  69. $controllerCls = \Qii\Config\Register::get(\Qii\Config\Consts::APP_DEFAULT_CONTROLLER_PREFIX) . '\\' . $controller;
  70. }
  71. $action = preg_replace('/(Action)$/i', "", $action);
  72. $filePath = \Qii\Autoloader\Psr4::getInstance()->searchMappedFile($controllerCls);
  73. if (!is_file($filePath)) {
  74. if ($env == 'product') return '';
  75. \Qii\Autoloader\Import::requires(Qii_DIR . DS . 'Exceptions' . DS . 'Error.php');
  76. call_user_func_array(array('\Qii\Exceptions\Error', 'index'), array($controller, $action));
  77. die();
  78. } else {
  79. \Qii::getInstance()->request->setControllerName($controller);
  80. \Qii::getInstance()->request->setActionName($action);
  81. \Qii::getInstance()->dispatcher->setRequest(\Qii::getInstance()->request);
  82. \Qii::getInstance()->dispatcher->dispatch($controller, $action, $e);
  83. die();
  84. }
  85. }
  86. ob_start();
  87. include(join(DS, array(Qii_DIR, 'Exceptions', 'View', 'error.php')));
  88. $html = ob_get_contents();
  89. ob_clean();
  90. if (!IS_CLI) {
  91. echo $html;
  92. return;
  93. }
  94. return (new \Qii\Response\Cli())->stdout(
  95. str_replace("&nbsp;"
  96. , " "
  97. , strip_tags(join(PHP_EOL, preg_replace("/[\n|\r\n]/", PHP_EOL, $message)))
  98. )
  99. );
  100. }
  101. /**
  102. * 获取指定文件的指定行内容
  103. *
  104. * @param String $fileName 文件名
  105. * @param Int $line 行号
  106. * @return String
  107. */
  108. public static function getLineMessage($fileName, $line)
  109. {
  110. $seekline = max(0, $line - 1);
  111. $spl = new \SplFileObject($fileName);
  112. $code = array();
  113. if ($line > 1) {
  114. $maxLine = 10;
  115. $firstLine = max(0, $seekline - $maxLine);
  116. $spl->seek($firstLine);
  117. $min = $seekline - $maxLine;
  118. $max = $seekline + $maxLine + 1;
  119. for ($i = $min; $i < $max; $i++) {
  120. $currentLine = $i + ($min < 0 ? abs($min) : 0) + 1;
  121. $color = $currentLine == $line ? ' color="red"' : '';
  122. if ($spl->eof()) break;
  123. if (IS_CLI) {
  124. $code[] = $currentLine . ($color != '' ? ' 行发生错误' : '') . rtrim($spl->current());
  125. } else {
  126. $code[] = '<font ' . $color . '>' . $currentLine . ':</font>' . "\t" . '<font ' . $color . '>' . htmlspecialchars(rtrim($spl->current())) . '</font>';
  127. }
  128. $spl->next();
  129. }
  130. } else {
  131. $spl->seek($seekline);
  132. if (IS_CLI) {
  133. $code[] = rtrim($spl->current());
  134. } else {
  135. $code[] = htmlspecialchars(rtrim($spl->current()));
  136. }
  137. }
  138. return IS_CLI ? PHP_EOL . join(PHP_EOL, $code) : '<pre style="font-weight:bold;">' . join("<br />", $code) . '</pre>';
  139. }
  140. /**
  141. * sprintf 格式化语言错误信息内容
  142. *
  143. *
  144. * Qii::e($message, $argv1, $argv2, ..., $line);
  145. * $message = sprintf($message, $argv1, $argv2, ...);
  146. * throw new \Qii_Exceptions_Errors($message, $line);
  147. */
  148. public static function e()
  149. {
  150. $argvs = func_get_args();
  151. $count = count($argvs);
  152. $message = array_shift($argvs);
  153. $line = (int)array_pop($argvs);
  154. if ($count == 2) {
  155. throw new \Qii\Exceptions\Errors($message, $line);
  156. }
  157. $message = vsprintf($message, $argvs);
  158. throw new \Qii\Exceptions\Errors($message, $line);
  159. }
  160. }