lithium\analysis\Debugger::trace()
Outputs a stack trace based on the supplied options.
Parameters
-
array
$options
Format for outputting stack trace. Available options are:
'args'
: A boolean indicating if arguments should be included.'depth'
: The maximum depth of the trace.'format'
: Eithernull
,'points'
or'array'
.'includeScope'
: A boolean indicating if items within scope should be included.'scope'
: Scope for items to include.'start'
: The depth to start with.'trace'
: A trace to use instead of generating one.
Returns
string|array|nullStack trace formatted according to 'format'
option.
Source
public static function trace(array $options = []) {
$defaults = [
'depth' => 999,
'format' => null,
'args' => false,
'start' => 0,
'scope' => [],
'trace' => [],
'includeScope' => true,
'closures' => true
];
$options += $defaults;
$backtrace = $options['trace'] ?: debug_backtrace();
$scope = $options['scope'];
$count = count($backtrace);
$back = [];
$traceDefault = [
'line' => '??', 'file' => '[internal]', 'class' => null, 'function' => '[main]'
];
for ($i = $options['start']; $i < $count && $i < $options['depth']; $i++) {
$trace = array_merge(['file' => '[internal]', 'line' => '??'], $backtrace[$i]);
$function = '[main]';
if (isset($backtrace[$i + 1])) {
$next = $backtrace[$i + 1] + $traceDefault;
$function = $next['function'];
if (!empty($next['class'])) {
$function = $next['class'] . '::' . $function . '(';
if ($options['args'] && isset($next['args'])) {
$args = array_map(['static', 'export'], $next['args']);
$function .= join(', ', $args);
}
$function .= ')';
}
}
if ($options['closures'] && strpos($function, '{closure}') !== false) {
$function = static::_closureDef($backtrace[$i], $function);
}
if (in_array($function, ['call_user_func_array', 'trigger_error'])) {
continue;
}
$trace['functionRef'] = $function;
if ($options['format'] === 'points' && $trace['file'] !== '[internal]') {
$back[] = ['file' => $trace['file'], 'line' => $trace['line']];
} elseif (is_string($options['format']) && $options['format'] !== 'array') {
$back[] = Text::insert($options['format'], array_map(
function($data) { return is_object($data) ? get_class($data) : $data; },
$trace
));
} elseif (empty($options['format'])) {
$back[] = $function . ' - ' . $trace['file'] . ', line ' . $trace['line'];
} else {
$back[] = $trace;
}
if (!empty($scope) && array_intersect_assoc($scope, $trace) == $scope) {
if (!$options['includeScope']) {
$back = array_slice($back, 0, count($back) - 1);
}
break;
}
}
if ($options['format'] === 'array' || $options['format'] === 'points') {
return $back;
}
return join("\n", $back);
}