spatie/backtrace
Spatie Backtrace provides a cleaner, easier-to-use alternative to PHP’s debug_backtrace. It returns a structured list of Frame objects with accurate file, line, class/method info, and optional arguments, making traces simpler to inspect and filter.
Installation:
composer require spatie/backtrace
No configuration is required—just start using it immediately.
First Use Case:
Replace debug_backtrace() with Spatie\Backtrace\Backtrace::create()->frames() for cleaner, more readable frame data:
use Spatie\Backtrace\Backtrace;
$frames = Backtrace::create()->frames();
$firstFrame = $frames[0];
echo "File: {$firstFrame->file}\n";
echo "Line: {$firstFrame->lineNumber}\n";
echo "Class: {$firstFrame->class}\n";
Key Starting Points:
applicationPath(base_path()) to filter vendor/application frames.Backtrace::createForThrowable($exception) for exceptions.Basic Frame Inspection:
$backtrace = Backtrace::create();
foreach ($backtrace->frames() as $frame) {
if ($frame->class === MyService::class) {
log("Found MyService at {$frame->file}:{$frame->lineNumber}");
}
}
Filtering Frames:
$frames = Backtrace::create()
->startingFromFrame(fn($frame) => $frame->class === Controller::class)
->frames();
$frames = Backtrace::create()->offset(2)->frames(); // Skip first 2 frames
Laravel-Specific Patterns:
$backtrace = Backtrace::create()
->applicationPath(base_path())
->trimFilePaths(); // Shortens paths (e.g., `app/Http/Controllers/...` instead of full path)
Exception Handling:
try {
// Risky code
} catch (Exception $e) {
$frames = Backtrace::createForThrowable($e);
// Log or display $frames for debugging
}
Argument/Object Inspection (Performance Note: Enable only when needed):
$backtrace = Backtrace::create()
->withArguments()
->withObject()
->reduceArguments(); // Convert complex args (e.g., DateTime) to strings
trimFilePaths() + applicationPath() to make logs cleaner.App\Exceptions\Handler).Backtrace::create() in unit tests to simulate call stacks:
$mockFrames = [new Frame(...), new Frame(...)];
$this->app->instance(Backtrace::class, fn() => new Backtrace($mockFrames));
Performance Overhead:
withArguments()/withObject(): Disables PHP’s zend.exception_ignore_args temporarily. Use sparingly in production.Path Trimming Edge Cases:
trimFilePaths() requires applicationPath() to be set first.->applicationPath(base_path()) before ->trimFilePaths().Vendor/Application Frame Misclassification:
artisan and Statamic’s please are treated as vendor files (even if in root).$frames = Backtrace::create()->frames()->filter(fn($frame) => $frame->file !== base_path('artisan'));
Closure/Serializable Objects:
null or [object].reduceArguments() to customize display for complex types.open_basedir Restrictions:
open_basedir, getSnippetAsString() may fail.try {
$snippet = $frame->getSnippetAsString();
} catch (Exception $e) {
$snippet = "Snippet unavailable (file outside open_basedir)";
}
Inspect Frame Properties:
dd($frame->toArray()); // Dump all properties for debugging
Custom Argument Reducers:
Carbon instances):
$backtrace = Backtrace::create()
->withArguments()
->reduceArguments([
new class implements ArgumentReducer {
public function execute($arg): ReducedArgumentContract {
return $arg instanceof Carbon
? new ReducedArgument($arg->toDateTimeString(), get_class($arg))
: UnReducedArgument::create();
}
}
]);
Laravel Artisan Commands:
->applicationPath(base_path()) to correctly classify frames in CLI commands.Testing Backtraces:
Backtrace::create() directly to avoid real call stacks:
$backtrace = Backtrace::create();
$backtrace->setFrames([new Frame(...)]); // Inject mock frames
Custom Frame Filtering:
Spatie\Backtrace\Frame or use startingFromFrame() for complex logic:
$backtrace->startingFromFrame(fn($frame) =>
str_contains($frame->file, 'app/Http') && $frame->class !== Controller::class
);
Snippet Customization:
getSnippetAsString() in a custom Frame class to highlight specific syntax.Argument Reducers:
ArgumentReducer for domain-specific types (e.g., Illuminate\Support\Collection).Laravel Service Provider:
Backtrace instance with default settings:
$this->app->singleton(Backtrace::class, fn() =>
Backtrace::create()
->applicationPath(base_path())
->trimFilePaths()
);
How can I help you explore Laravel packages today?