A better way to work with a backtrace in PHP
To get the backtrace in PHP, you can use the debug_backtrace
function. By default, it can be hard to work with. Using our newly released spatie/backtrace package, this becomes much simpler.
Let's dive in!
Why we created this package
The debug_backtrace
is one of those PHP that has a terrible DX. It returns an array with frames, but those frames are hard to work with. Let's take a look at some example output.
0 => [
"file" => "/Users/freek/dev/code/backtrace/src/Backtrace.php"
"line" => 85
"function" => "getRawFrames"
"class" => "Spatie\Backtrace\Backtrace"
]
1 => [
"file" => "/Users/freek/dev/code/backtrace/tests/BacktraceTest.php"
"line" => 15
"function" => "frames"
"class" => "Spatie\Backtrace\Backtrace"
"type" => "->"
]
2 =>[
"file" => "/Users/freek/dev/code/backtrace/vendor/phpunit/phpunit/src/Framework/TestCase.php"
"line" => 1536
"function" => "it_can_create_a_backtrace"
"class" => "Spatie\Backtrace\Tests\BacktraceTest"
]
// more frames
Looking at this output, you might think that it_can_create_a_backtrace
is defined in /Users/freek/dev/code/backtrace/vendor/phpunit/phpunit/src/Framework/TestCase.php
, but it's actually defined in the file
of the previous frame: /Users/freek/dev/code/backtrace/tests/BacktraceTest.php
This is very confusing to work with, and this is the main reason we created a backtrace package. The output of our package will actually report frame properties as you expect them.
If you're a "professional" programmer, you might like to work with bitmasks.
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT)
As an "amateur" developer, I prefer to work with chainable method calls to configure things.
Working with spatie/backtrace
Here's how you can get the frames of the backtrace using our package:
// returns an array with `Spatie\Backtrace\Frame` instances
$frames = Spatie\Backtrace\Backtrace::create()->frames();
$firstFrame = $frames[0];
$firstFrame->file; // returns the file name
$firstFrame->lineNumber; // returns the line number
$firstFrame->class; // returns the class name
$firstFrame->method; // returns the method name
In all frames, we "fixed" the output of debug_backtrace
: you'll always find the class
and method
a frame inside the file
reported by the frame.
For performance reasons, the frames of the backtrace will not contain the arguments of the called functions. If you
want to add those use the withArguments
method.
$frames = Spatie\Backtrace\Backtrace::create()->withArguments()->frames();
$argumentsOfFirstFrame = $frames[0]->arguments // returns an array with arguments
If you only want to have the frames starting from a particular frame in the backtrace, you can use
the startingFromFrame
method:
use Spatie\Backtrace\Backtrace;
use Spatie\Backtrace\Frame;
$frames = Backtrace::create()
->startingFromFrame(function (Frame $frame) {
return $frame->class === MyClass::class;
})
->frames();
With this code, all frames before the frame that concerns MyClass
will have been filtered out.
Alternatively, you can use the offSet
method, which will skip the given number of frames. In this example, the first two frames will not end up in $frames
.
$frames = Spatie\Backtrace\Backtrace::create()
->offset(2)
->frames();
To only get a specific number of frames, use the limit
function. In this example, we'll only get the first two frames.
$frames = Spatie\Backtrace\Backtrace::create()
->limit(2)
->frames();
In closing
Our spatie/backtrace package makes working with a backtrace much more enjoyable. It contains a few more options. Head over to the readme on GitHub to learn more.
I've practiced YAGNI here and only added the bare minimum for now. We might add some helper methods to the Frame
object in the future, so you can quickly check if a particular method is called statically or if the frame was added for a global function.
Be sure to take a look at this list of open source packages our team has previously made.
If you would like to support us, consider purchasing one of our paid products. At the moment of writing, we're having a Black Week sale where you can grab any of our products with a significant discount. Head over to our products page to know more.
What an interesting post. Thanks for sharing this one! house painting North Port FL