Есть ли дамп стека довольно печати?
Скажем прямо, debug_backtrace()
не очень debug_backtrace()
. Кто-нибудь кодировал обертку?
А какая ваша любимая var_dump()
(которую можно использовать в коммерческих проектах, поэтому нет GPL (хотя с LGPL все в порядке))
Смотрите также: Более симпатичная/информативная альтернатива Var_dump в PHP?
Шесть лет - и десять тысяч просмотров этого вопроса - позже, и я все еще использую это. Это не очень хорошо выглядит на экране, как Kint (что отлично).
Это простой текст, который я могу отправить себе по электронной почте в автоматических отчетах об ошибках и отображать в консоли разработчика браузера с помощью ChromePhp.
/**
* @brief Returns an HTML formatted string showing details of the backtrace
*
* Example:
*
* F:\Dropbox\programs\Xampp\htdocs\api\q.php:48 e(373, 'beer', 'curry')
* F:\Dropbox\programs\Xampp\htdocs\api\q.php:53 d(26366, 28255, 8364)
* F:\Dropbox\programs\Xampp\htdocs\api\q.php:58 c()
* F:\Dropbox\programs\Xampp\htdocs\api\q.php:63 b(1283, 15488, 29369)
* F:\Dropbox\programs\Xampp\htdocs\api\q.php:72 a(788, 6077, 25010)
*/
function FormatBacktrace()
{
$result = '<h4>Backtrace</h4>';
foreach (debug_backtrace() as $trace)
{
if ($trace['function'] ==__FUNCTION__)
continue;
$parameters = is_array($trace['args']) ? implode(", ",$trace['args']) : "";
if (array_key_exists('class', $trace))
$result .= sprintf("%s:%s %s::%s(%s)<br>",
$trace['file'],
$trace['line'],
$trace['class'],
$trace['function'],
$parameters);
else
$result .= sprintf("%s:%s %s(%s)<br>",
$trace['file'],
$trace['line'],
$trace['function'],
$parameters);
}
return $result;
}
Ответы
Ответ 1
расширение Xdebug может распечатать stacktraces с настраиваемым Степень многословия.
![Xdebug stacktrace image]()
Он также предлагает некоторые дополнительные функции var_dump(), такие как раскраска синтаксиса:
![Colored var_dump()]()
Edit:
Относительно включения Xdebug в коммерческий проект.
лицензия Xdebug имеет всего несколько терминов и кажется довольно разрешительной.
Xdebug является расширением C. Поскольку такое перераспределение его или его части в вашем проекте может быть несколько сложным. В зависимости от ваших требований я вижу несколько вариантов:
- Попросите конечного пользователя установить Xdebug из дистрибутива Linux или DLL с сайта.
- Распространять файлы .dll и .so для всех поддерживаемых платформ.
- Создайте исходный код конечного пользователя
- Распространение пользовательской сборки PHP
Ответ 2
У вас также есть kint
(репозиторий github), у которого есть пакет composer
в репозитории packagist
Поэтому либо загрузите библиотеку вручную, либо с помощью composer
, это всего лишь вопрос:
$ composer init
$ composer require raveren/kint
$ composer install
Затем вместо ini_set('display_errors', 'On');
я предпочитаю использовать этот простой обработчик в моем основном (первом) включаемом файле:
if ( getenv('__project_env__') === 'DEV') {
error_reporting(E_ALL | E_STRICT);
function shutdown_handler() {
$error = error_get_last();
Kint::trace();
Kint::dump($error);
}
register_shutdown_function('shutdown_handler');
} else {
...
}
При установке __project_env__
в виртуальном хосте Apache (SetEnv __project_env__ "DEV"
), чтобы не загрязнять разные ветки репозитория git
, где проект живет элементами конфигурации, которые по сути являются environmental
- В DEV: я получаю отладку
- В PROD по умолчанию молчит
Вот скриншот того, как выглядит трассировка (каждый шаг является разборным):
![Kint stack trace]()
(источник: github.io)
Ответ 3
Вот моя симпатичная оболочка для печати, предназначенная для вывода без браузера, то есть журналов ошибок или консоли:
function stackTrace() {
$stack = debug_backtrace();
$output = '';
$stackLen = count($stack);
for ($i = 1; $i < $stackLen; $i++) {
$entry = $stack[$i];
$func = $entry['function'] . '(';
$argsLen = count($entry['args']);
for ($j = 0; $j < $argsLen; $j++) {
$func .= $entry['args'][$j];
if ($j < $argsLen - 1) $func .= ', ';
}
$func .= ')';
$output .= $entry['file'] . ':' . $entry['line'] . ' - ' . $func . PHP_EOL;
}
return $output;
}
Ответ 4
jhurliman довольно печатный метод stackTrace выше действительно замечательный. Но для меня это создавало множество PHP-предупреждений, которые также загромождали журнал. Я добавил немного больше ошибок и проверки типов, что приводит к очень хорошей трассировке стека в журналах. Вот модифицированная версия jhurliman кода:
function stackTrace() {
$stack = debug_backtrace();
$output = '';
$stackLen = count($stack);
for ($i = 1; $i < $stackLen; $i++) {
$entry = $stack[$i];
$func = $entry['function'] . '(';
$argsLen = count($entry['args']);
for ($j = 0; $j < $argsLen; $j++) {
$my_entry = $entry['args'][$j];
if (is_string($my_entry)) {
$func .= $my_entry;
}
if ($j < $argsLen - 1) $func .= ', ';
}
$func .= ')';
$entry_file = 'NO_FILE';
if (array_key_exists('file', $entry)) {
$entry_file = $entry['file'];
}
$entry_line = 'NO_LINE';
if (array_key_exists('line', $entry)) {
$entry_line = $entry['line'];
}
$output .= $entry_file . ':' . $entry_line . ' - ' . $func . PHP_EOL;
}
return $output;
}
Ответ 5
Здесь "pretty print" var_dump
function vdump() {
$args = func_get_args();
$backtrace = debug_backtrace();
$code = file($backtrace[0]['file']);
echo "<pre style='background: #eee; border: 1px solid #aaa; clear: both; overflow: auto; padding: 10px; text-align: left; margin-bottom: 5px'>";
echo "<b>".htmlspecialchars(trim($code[$backtrace[0]['line']-1]))."</b>\n";
echo "\n";
ob_start();
foreach ($args as $arg)
var_dump($arg);
$str = ob_get_contents();
ob_end_clean();
$str = preg_replace('/=>(\s+)/', ' => ', $str);
$str = preg_replace('/ => NULL/', ' → <b style="color: #000">NULL</b>', $str);
$str = preg_replace('/}\n(\s+)\[/', "}\n\n".'$1[', $str);
$str = preg_replace('/ (float|int)\((\-?[\d\.]+)\)/', " <span style='color: #888'>$1</span> <b style='color: brown'>$2</b>", $str);
$str = preg_replace('/array\((\d+)\) {\s+}\n/', "<span style='color: #888'>array•$1</span> <b style='color: brown'>[]</b>", $str);
$str = preg_replace('/ string\((\d+)\) \"(.*)\"/', " <span style='color: #888'>str•$1</span> <b style='color: brown'>'$2'</b>", $str);
$str = preg_replace('/\[\"(.+)\"\] => /', "<span style='color: purple'>'$1'</span> → ", $str);
$str = preg_replace('/object\((\S+)\)#(\d+) \((\d+)\) {/', "<span style='color: #888'>obj•$2</span> <b style='color: #0C9136'>$1[$3]</b> {", $str);
$str = str_replace("bool(false)", "<span style='color:#888'>bool•</span><span style='color: red'>false</span>", $str);
$str = str_replace("bool(true)", "<span style='color:#888'>bool•</span><span style='color: green'>true</span>", $str);
echo $str;
echo "</pre>";
echo "<div class='block tiny_text' style='margin-left: 10px'>";
echo "Sizes: ";
foreach ($args as $k => $arg) {
if ($k > 0) echo ",";
echo count($arg);
}
echo "</div>";
}
Ответ 6
Zend_Debug::dump($var);
http://framework.zend.com/manual/en/zend.debug.html
Ответ 7
Собираюсь добавить мой ответ на остальные ответы здесь.
Если у вас установлены bootstrap и jquery, он еще более полезен и компактен, но не обязателен.
function prettyPrintBackTrace() {
$backtrace = "\n<b><u>Full Backtrace</u></b>\n<script>function toggleBackTraceTwirl(self) {\$('span', self).toggleClass('glyphicon-menu-up glyphicon-menu-down');}</script>";
foreach (debug_backtrace() as $key => $trace) {
if(($trace['function'] ==__FUNCTION__) || ($trace['function'] == "fail")) {continue;}
$class = (array_key_exists('class', $trace) ? "class <u>({$trace['class']})</u>" : false);
$exp = explode("/",$trace['file']);
$exp[count($exp)-1] = "<b>" . end($exp) . "</b>";;
$filename = implode("/",array_splice($exp, -4));
$backtrace .= "/{$filename}:{$trace['line']}, ";
if((isset($trace['args'])) && (is_array($trace['args']))) {
if( (is_string($trace['args'][0])) && (substr($trace['args'][0],-4) == ".php") && (count($trace['args'] == 1)) ) {
// It was most likely a php include of some sort.
$exp = explode("/",$trace['args'][0]);
$filename = implode("/",array_splice($exp, -2));
$backtrace .= "function <i>{$trace['function']}(<b>{$filename}</b>)</i>\n";
} else {
// Finish the line and move on.
$backtrace .= "function <i>{$trace['function']}()</i> <a href='#' data-target='#backtraceparameters{$key}' onClick='toggleBackTraceTwirl(this)' data-toggle='collapse'><span class='glyphicon glyphicon-menu-down'></span></a>\n";
$backtrace .= "<div id='backtraceparameters{$key}' class='collapse'>";
$args = array();
foreach($trace['args'] as $key => $val) {
if($val) $args[(!is_numeric($key) ? "key" : false)] = $val;
}
foreach($args as $count => $a) {
$backtrace .= ($count != (count($args) -1) ? "├" : "└");
$value = $a;
if($a === true) $value = "<i>true</i>";
if($a === false) $value = "<i>f alse</i>";
$backtrace .= "─ ".(!is_numeric($count) ? $count." " : false).var_export($value,1)."\n";
}
$backtrace .= "</div>";
}
}
}
return $backtrace;
}
Я надеюсь, что это помогает кому-то. Я пытался сделать его максимально компактным.
Ответ 8
Мой любимый var_dump
фрагмент - это тот, который я сделал много лет назад и с тех пор работаю над совершенствованием. Я знаю, что там есть lib, которые создают действительно симпатичные дампы с аккордеонными меню и все, но я просто хочу простой макет, легко читаемый, может быть, немного HTML и как переносимый, как один метод кода. Таким образом, моя функция:
function preDump() { // use string "noEcho" to just get a string return only
$args = func_get_args();
$doEcho = TRUE; $sb;
if ($args) {
$sb = '<div style="margin: 1em 0;"><fieldset style="display:inline-block;padding:0em 3em 1em 1em;"><legend><b>preDump: '.count($args).' Parameters Found.</b></legend>';
foreach (func_get_args() as $arg) {
if (gettype($arg) == 'string') if ($arg == 'noEcho') { $doEcho = FALSE; $sb = preg_replace('/(preDump: )[0-9]+/', 'preDump: '.(count($args)-1), $sb); continue; }
$sb .= '<pre data-type="'.gettype($arg).'"';
switch (gettype($arg)) {
case "boolean":
case "integer":
$sb .= ' data-dump="json_encode"><p style="border-bottom:1px solid;margin:0;padding:0 0 0 1em;"><b>gettype('.gettype($arg).')</b></p><p>';
$sb .= json_encode($arg);
break;
case "string":
$sb .= ' data-dump="echo"><p style="border-bottom:1px solid;margin:0;padding:0 0 0 1em;"><b>gettype('.gettype($arg).')</b></p><p>';
$sb .= $arg;
break;
default:
$sb .= ' data-dump="var_dump"';
if (is_object($arg)) $sb .= 'data-class="'.get_class($arg).'"';
$sb .= '><p style="border-bottom:1px solid;margin:0;padding:0 0 0 1em;"><b>gettype('.gettype($arg).')';
if (is_object($arg)) $sb .= ' ['.get_class($arg).']';
$sb .= '</b></p><p>';
ob_start();
var_dump($arg);
$sb .= ob_get_clean();
if (ob_get_length()) ob_end_clean();
}
$sb .= '</p></pre>';
}
$sb .= '</fieldset></div>';
}
else {
$sb = '<div style="margin: 1em 0;"><fieldset style="display:inline-block;"><legend><b>preDump: [ERROR]</b></legend><h3>No Parameters Found</h3></fieldset></div>';
}
if ($doEcho) echo($sb);
return $sb;
}
Использование очень просто. Он принимает бесконечные параметры. Кроме того, он показывает все в рамках простого fieldsets
для каждого вызванного preDump
, а также разделяет каждый параметр на свой собственный тег pre
, что делает его чистым и легко читаемым. Каждый тег pre
также содержит заголовок, показывающий gettype
каждого параметра, и, если он является объектом, он также будет показывать class name
.
Используйте так же просто, как var_dump();
preDump(TRUE, 101, 'this is a string', array( 'array', 'here' ), (object)array ( 'this' => 'is', 'an' => 'object' ), $someXMLvariable);
Вы также можете использовать его, чтобы получить дамп в виде простой строки, а затем эхо, если вы считаете нужным:
$bob = preDump($someParam1, $someParam2, 'noEcho'); // 'noEcho' causes it to return as string only