Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Backtrace Laravel Package

spatie/backtrace

A cleaner, more useful PHP backtrace than debug_backtrace(). Create a Backtrace, get frames as typed Frame objects with correct file, line, class/method, and optional arguments, making stack traces easier to inspect, filter, and work with.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

Install via Composer:

composer require spatie/backtrace

First Use Case: Basic Backtrace

use Spatie\Backtrace\Backtrace;

// Get all frames as Frame objects
$frames = Backtrace::create()->frames();

// Access first frame properties
$firstFrame = $frames[0];
echo $firstFrame->file;       // File path
echo $firstFrame->lineNumber; // Line number
echo $firstFrame->class;      // Class name (null for functions)

Laravel-Specific Quick Start

use Spatie\Backtrace\Backtrace;

// Configure for Laravel
$backtrace = Backtrace::create()
    ->applicationPath(base_path())
    ->trimFilePaths();

// Get application frames only
$appFrames = $backtrace->frames();

Implementation Patterns

1. Debugging Workflow

// In a service or controller
public function handleRequest()
{
    try {
        // Business logic
    } catch (\Exception $e) {
        $backtrace = Backtrace::createForThrowable($e)
            ->withArguments()
            ->reduceArguments();

        // Log or display enhanced backtrace
        $this->logError($e, $backtrace->frames());
    }
}

2. Custom Argument Reduction

// Create custom reducer for complex objects
class UserArgumentReducer implements ArgumentReducer
{
    public function execute($argument): ReducedArgumentContract
    {
        if (!$argument instanceof User) {
            return UnReducedArgument::create();
        }

        return new ReducedArgument(
            $argument->id . ' (' . $argument->email . ')',
            get_class($argument)
        );
    }
}

// Apply in backtrace
$backtrace = Backtrace::create()
    ->withArguments()
    ->reduceArguments(
        ArgumentReducers::default([
            new UserArgumentReducer()
        ])
    );

3. Filtering Application Frames

// Get only application frames (excluding vendor)
$appFrames = Backtrace::create()
    ->applicationPath(base_path())
    ->frames()
    ->filter(fn($frame) => $frame->applicationFrame);

4. Code Snippet Integration

// Display code context in error messages
$frame = Backtrace::create()->frames()[0];
$snippet = $frame->getSnippetAsString(5); // 5 lines context

5. Exception Handler Integration

// In Laravel's App\Exceptions\Handler
public function render($request, Throwable $exception)
{
    $backtrace = Backtrace::createForThrowable($exception)
        ->withArguments()
        ->reduceArguments()
        ->applicationPath(base_path())
        ->trimFilePaths();

    return response()->json([
        'error' => $exception->getMessage(),
        'trace' => $backtrace->frames()
    ]);
}

6. CLI Command Debugging

// In a Laravel command
protected function handle()
{
    $backtrace = Backtrace::create()
        ->startingFromFrame(fn($frame) => $frame->class === self::class)
        ->limit(10);

    $this->info('Execution trace:');
    foreach ($backtrace->frames() as $frame) {
        $this->line(sprintf(
            '[%s:%d] %s::%s',
            $frame->file,
            $frame->lineNumber,
            $frame->class ?? 'function',
            $frame->method
        ));
    }
}

Gotchas and Tips

Common Pitfalls

  1. Argument Collection Overhead:

    • withArguments() can significantly impact performance
    • Only use when debugging, not in production
    • Tip: Wrap in APP_DEBUG check:
      if (app()->environment('local')) {
          $backtrace->withArguments();
      }
      
  2. Vendor Frame Misclassification:

    • Laravel's artisan and Statamic's please are treated as vendor files
    • Workaround: Explicitly mark them as application frames if needed
  3. File Path Handling:

    • trimFilePaths() requires applicationPath() to be set first
    • Tip: Use with realpath() for consistency:
      ->applicationPath(realpath(base_path()))
      
  4. Closure Arguments:

    • Anonymous functions may not show arguments properly
    • Tip: Use named functions or closures with bindTo() for better visibility
  5. PHP Configuration:

    • zend.exception_ignore_args must be 0 for throwable arguments
    • Tip: Set in .env:
      zend.exception_ignore_args=0
      

Debugging Tips

  1. Frame Inspection:

    // Dump all frame properties
    collect($frames)->each(function($frame) {
        dd([
            'file' => $frame->file,
            'line' => $frame->lineNumber,
            'class' => $frame->class,
            'method' => $frame->method,
            'args' => $frame->arguments,
            'object' => $frame->object,
            'app_frame' => $frame->applicationFrame
        ]);
    });
    
  2. Argument Reduction Debugging:

    // Check which arguments are being reduced
    $backtrace->reduceArguments(function($argument) {
        return new ReducedArgument(
            'REDACTED',
            get_class($argument)
        );
    });
    
  3. Performance Profiling:

    // Benchmark backtrace generation
    $start = microtime(true);
    $frames = Backtrace::create()->frames();
    $time = microtime(true) - $start;
    

Advanced Patterns

  1. Custom Frame Filtering:

    // Filter frames by package
    $vendorFrames = $backtrace->frames()->filter(function($frame) {
        return str_starts_with($frame->file, base_path('vendor'));
    });
    
  2. Backtrace Comparison:

    // Compare two backtraces
    $original = Backtrace::create()->frames();
    $modified = Backtrace::create()->frames();
    
    $differences = collect($original)->zip($modified)
        ->filter(fn($pair) => $pair[0]->lineNumber !== $pair[1]->lineNumber)
        ->keys();
    
  3. Backtrace Caching:

    // Cache backtrace for expensive operations
    $cacheKey = 'backtrace:'.md5($request->ip());
    $frames = Cache::remember($cacheKey, now()->addMinutes(5), function() {
        return Backtrace::create()->limit(20)->frames();
    });
    
  4. Integration with Laravel Scout:

    // Use backtrace for search analytics
    $searchBacktrace = Backtrace::create()
        ->startingFromFrame(fn($frame) => $frame->class === SearchRequest::class)
        ->limit(5);
    
    SearchAnalytics::create([
        'query' => $request->query,
        'backtrace' => json_encode($searchBacktrace->frames()),
        'user_id' => auth()->id()
    ]);
    

Configuration Quirks

  1. Application Path Detection:

    • The package considers files outside vendor/ as application frames by default
    • Tip: Override with custom logic:
      ->applicationPath(base_path())
      ->customApplicationFrameDetector(function($file) {
          return !str_contains($file, ['node_modules', 'bower_components']);
      })
      
  2. File Path Normalization:

    • Windows paths may cause issues with string comparison
    • Tip: Normalize paths:
      ->applicationPath(str_replace('\\', '/', base_path()))
      
  3. Memory Management:

    • Large backtraces with arguments can consume significant memory
    • Tip: Use limit() to control size:
      ->limit(10) // Only keep most recent 10 frames
      

Extension Points

  1. Custom Frame Properties:

    // Add custom metadata to frames
    $backtrace->frames()->each(function($frame) {
        $frame->custom = [
            'is_critical' => $frame->lineNumber > 100,
            'package' => $this->detectPackage($frame->file)
        ];
    });
    
  2. Backtrace Decorators:

    // Create reusable backtrace enhancers
    class DebugDecorator
    {
        public function __invoke(Backtrace $backtrace)
        {
            return $backtrace
                ->withArguments()
                ->reduceArguments()
                ->applicationPath(base_path())
                ->trimFilePaths();
        }
    }
    
    // Usage
    $debugBacktrace = (new DebugDecorator())(Backtrace::create());
    
  3. Backtrace Serialization:

    // Convert backtrace to JSON
    $serialized = $backtrace->frames()->map(function($frame) {
        return [
            'file' => $frame->file,
            'line' => $frame->lineNumber,
            'class' => $frame->class,
            'method' => $frame->method,
            'args' => $frame
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony