Installation Add the package via Composer:
composer require openforce-jp/debug-container
Publish the config (if needed):
php artisan vendor:publish --provider="Openforce\DebugContainer\DebugContainerServiceProvider"
Basic Usage
The package provides a DebugContainer facade to inspect and manipulate Laravel's service container at runtime. Start with:
use Openforce\DebugContainer\Facades\DebugContainer;
// List all registered bindings
$bindings = DebugContainer::bindings();
dd($bindings);
// Inspect a specific binding
$resolver = DebugContainer::resolver('App\Services\SomeService');
dd($resolver);
First Use Case Debug unresolved dependencies or circular references:
try {
app()->make('App\Services\ProblemService');
} catch (\Illuminate\Contracts\Container\BindingResolutionException $e) {
DebugContainer::inspectBinding('App\Services\ProblemService');
// Outputs dependency tree, aliases, and context
}
Debugging Service Resolution
Use DebugContainer::inspectBinding() to trace how a service is resolved:
$debugInfo = DebugContainer::inspectBinding('App\Services\UserService');
// Returns:
// - Class name
// - Concrete instance (if resolved)
// - Dependencies (with their bindings)
// - Aliases (if any)
Dynamic Container Manipulation Temporarily override bindings for testing:
DebugContainer::override('App\Services\PaymentGateway', fn() => new StripeGateway());
// Use in tests or debug scenarios
Integration with Laravel Debugbar Extend Laravel Debugbar to include container insights:
Debugbar::addCollector(new class extends DebugbarCollector {
public function collect()
{
return [
'container' => [
'bindings' => DebugContainer::bindings(),
'singleton_count' => DebugContainer::singletonCount(),
],
];
}
});
Mocking Container Bindings Replace real services with mocks in tests:
DebugContainer::mock('App\Repositories\UserRepository', fn() => $this->createMock(UserRepository::class));
Asserting Container State Verify bindings exist or are singletons:
$this->assertTrue(DebugContainer::isBound('App\Services\Logger'));
$this->assertTrue(DebugContainer::isSingleton('App\Services\Logger'));
Performance Overhead
bindings()) can be slow. Cache results if used frequently:
$bindings = cache()->remember('debug.bindings', now()->addHours(1), fn() => DebugContainer::bindings());
Thread Safety
override() sparingly.Binding Resolution Exceptions
inspectBinding() may throw exceptions if the binding doesn’t exist. Handle gracefully:
try {
DebugContainer::inspectBinding('NonExistentService');
} catch (\InvalidArgumentException $e) {
// Log or ignore
}
Circular Dependency Detection
Use DebugContainer::inspectBinding() to spot circular references:
$debugInfo = DebugContainer::inspectBinding('App\Services\CircularService');
// Look for recursive dependency chains in the output.
Singleton Leaks Check for unintended singleton bindings:
$singletons = DebugContainer::singletons();
dd(array_filter($singletons, fn($binding) => str_contains($binding, 'UnexpectedSingleton')));
Config Quirks
ContextualBindingBuilder) may require manual integration.Custom Inspectors
Extend the DebugContainer facade to add domain-specific inspection logic:
DebugContainer::extend('app', function ($binding) {
return [
'is_app_service' => str_starts_with($binding, 'App\\'),
'namespace' => 'App',
];
});
Event Listeners
Hook into container events (e.g., BindingResolved) for real-time debugging:
app()->resolving(function ($object, $abstract) {
if (str_contains($abstract, 'DebugTarget')) {
DebugContainer::logResolution($abstract, $object);
}
});
CLI Integration Add a custom Artisan command for container diagnostics:
php artisan debug:container --service=App\Services\UserService
How can I help you explore Laravel packages today?