Стандартый вывод exception битрикса не достаточно информативен + не поддерживается цепочка эксепшенов.
Я решил сделать свой вывод.
После поисков в ядре оказалось что рендером эксепшенов занимается класс \Bitrix\Main\Diag\HttpExceptionHandlerOutput
Создаём два класса:
и
Регистрируем новый объект вывода (например init.php)
\Bitrix\Main\Application::getInstance()->getExceptionHandler()->setHandlerOutput(new ExceptionHandlerOutput());
Теперь если цепочка эсепшенов будет выглядеть так:
а если поставить константу define('FULL_EXCEPTION',true); оно же будет выглядеть так:
Прошу прощения что без особых подробностей, времени не хватает(((
Если что не понятно пишите в комментариях, помогу чем смогу.
ВНИМАНИЕ! Работает в битрикс >= 14.0.8
Я решил сделать свой вывод.
После поисков в ядре оказалось что рендером эксепшенов занимается класс \Bitrix\Main\Diag\HttpExceptionHandlerOutput
Создаём два класса:
<?php /** * User: James Gerat * Date: 21.05.14 * Time: 19:33 */ use Bitrix\Main\Application; use Bitrix\Main\Diag\HttpExceptionHandlerOutput; use Bitrix\Main\HttpRequest; class ExceptionHandlerOutput extends HttpExceptionHandlerOutput { function renderExceptionMessage(\Exception $exception, $debug = false) { if($debug) { if(defined('FULL_EXCEPTION') && FULL_EXCEPTION === true) { $this->renderExceptionFull($exception,$debug); $this->showEnvironment(); } else { $this->renderStandardException($exception,$debug); } } else { parent::renderExceptionMessage($exception,$debug); } } private function renderStandardException(\Exception $exception, $debug = false) { parent::renderExceptionMessage($exception,$debug); $e = $exception->getPrevious(); if($e instanceof \Exception) { $this->renderStandardException($e,$debug); } } private function renderExceptionFull(\Exception $exception, $debug = false) { $this->renderExceptionFullMessage($exception,$debug); $e = $exception->getPrevious(); if($e instanceof \Exception) { $this->renderExceptionFull($e,$debug); } } private function renderExceptionFullMessage(\Exception $exception, $debug = false) { if ($debug) { echo ExceptionHandlerFormatter::format($exception, true); } else { parent::renderExceptionMessage($exception,$debug); } } private function showEnvironment() { $context = Application::getInstance()->getContext(); $request = $context->getRequest(); echo '<pre>$_REQUEST'."\n".print_r($request->toArray(),true).'</pre>'; if($request instanceof HttpRequest) { echo '<pre>$_GET'."\n".print_r($request->getQueryList()->toArray(),true).'</pre>'; echo '<pre>$_POST'."\n".print_r($request->getPostList()->toArray(),true).'</pre>'; echo '<pre>$_COOKIE'."\n".print_r($request->getCookieList()->toArray(),true).'</pre>'; echo '<pre>$_FILES'."\n".print_r($request->getFileList()->toArray(),true).'</pre>'; echo '<pre>UserAgent'."\n".print_r($request->getUserAgent(),true).'</pre>'; } echo '<pre>$_SERVER'."\n".print_r($context->getServer()->toArray(),true).'</pre>'; echo '<pre>$_ENV'."\n".print_r($context->getEnvironment()->toArray(),true).'</pre>'; } } |
<?php /** * User: James Gerat * Date: 21.05.14 * Time: 20:37 */ use Bitrix\Main; class ExceptionHandlerFormatter { const MAX_CHARS = 30; public static function format(\Exception $exception, $htmlMode = false) { $result = '['.get_class($exception).'] '; if ($exception instanceof \ErrorException) $result .= static::severityToString($exception->getSeverity()); $result .= "\n".static::getMessage($exception)."\n"; if ($exception instanceof Main\DB\SqlQueryException) $result .= $exception->getQuery()."\n"; $fileLink = static::getFileLink($exception->getFile(), $exception->getLine()); $result .= $fileLink.(empty($fileLink) ? "" : "\n"); if ($htmlMode) $result = Main\Text\String::htmlEncode($result); $prevArg = null; $trace = static::getTrace($exception); foreach ($trace as $traceNum => $traceInfo) { if ($htmlMode) $result .= "<hr>"; $traceLine = '#'.$traceNum.': '; if (array_key_exists('class', $traceInfo)) $traceLine .= $traceInfo['class'].$traceInfo['type']; if (array_key_exists('function', $traceInfo)) { $traceLine .= $traceInfo['function']; $traceLine .= static::getArguments($traceInfo['args']); } if ($htmlMode) $traceLine = Main\Text\String::htmlEncode($traceLine); if (array_key_exists('file', $traceInfo)) $traceLine .= "\n\t".static::getFileLink($traceInfo['file'], $traceInfo['line']); else $traceLine .= "\n\t".static::getFileLink(null, null); $result .= $traceLine. "\n"; } if ($htmlMode) $result = '<pre class="exception">'.$result.'</pre>'; return $result; } protected static function getTrace(\Exception $exception) { $backtrace = $exception->getTrace(); $exceptionHandlerClass = "Bitrix\\Main\\Diag\\ExceptionHandler"; $result = array(); foreach ($backtrace as $item) { if (array_key_exists('class', $item) && ($item['class'] == $exceptionHandlerClass)) continue; $result[] = $item; } return $result; } protected static function getMessage(\Exception $exception) { return $exception->getMessage().' ('.$exception->getCode().')'; } public static function severityToString($severity) { switch ($severity) { case 1: return 'E_ERROR'; break; case 2: return 'E_WARNING'; break; case 4: return 'E_PARSE'; break; case 8: return 'E_NOTICE'; break; case 16: return 'E_CORE_ERROR'; break; case 32: return 'E_CORE_WARNING'; break; case 64: return 'E_COMPILE_ERROR'; break; case 128: return 'E_COMPILE_WARNING'; break; case 256: return 'E_USER_ERROR'; break; case 512: return 'E_USER_WARNING'; break; case 1024: return 'E_USER_NOTICE'; break; case 2048: return 'E_STRICT'; break; case 4096: return 'E_RECOVERABLE_ERROR'; break; case 8192: return 'E_DEPRECATED'; break; case 16384: return 'E_USER_DEPRECATED'; break; case 30719: return 'E_ALL'; break; default: return 'UNKNOWN'; break; } } protected static function getArguments($args) { if (!is_null($args)) { $argsTmp = array(); foreach ($args as $arg) $argsTmp[] = static::convertArgumentToString($arg); return "(\n" . implode(",\n", $argsTmp) . "\n)"; } return '()'; } protected static function convertArgumentToString($arg) { $result = null; switch (gettype($arg)) { case 'boolean': $result = $arg ? 'true' : 'false'; break; case 'NULL': $result = 'null'; break; case 'integer': case 'double': case 'float': $result = (string) $arg; break; case 'string': if (is_callable($arg, false, $callableName)) { $result = 'fs:'.$callableName; } elseif (class_exists($arg, false)) { $result = 'c:'.$arg; } elseif (interface_exists($arg, false)) { $result = 'i:'.$arg; } else { if (strlen($arg) > static::MAX_CHARS) $result = '"'.substr($arg, 0, static::MAX_CHARS / 2).'...'.substr($arg, -static::MAX_CHARS / 2).'" ('.strlen($arg).')'; else $result = '"'.$arg.'"'; } break; case 'array': if (is_callable($arg, false, $callableName)) $result = 'fa:'.$callableName; else $result = print_r($arg,true);//'array('.count($arg).')'; break; case 'object': $result = print_r($arg,true);//'['.get_class($arg).']'; break; case 'resource': $result = 'r:'.get_resource_type($arg); break; default: $result = 'unknown type'; break; } //return str_replace("\n", '\n', $result); return $result; } protected static function getFileLink($file, $line) { if (!is_null($file) && !empty($file)) { /** for WIN */ $file = Main\IO\Path::normalize($file); return str_replace(Main\Application::getDocumentRoot(),'',$file).':'.$line; } return ""; } } |
\Bitrix\Main\Application::getInstance()->getExceptionHandler()->setHandlerOutput(new ExceptionHandlerOutput());
Теперь если цепочка эсепшенов будет выглядеть так:
а если поставить константу define('FULL_EXCEPTION',true); оно же будет выглядеть так:
Прошу прощения что без особых подробностей, времени не хватает(((
Если что не понятно пишите в комментариях, помогу чем смогу.
ВНИМАНИЕ! Работает в битрикс >= 14.0.8