symfony/error-handler
Symfony ErrorHandler provides robust error and exception handling tools for PHP. Enable debug mode, register an error handler, and use DebugClassLoader for better stack traces. Convert PHP notices/warnings into exceptions and wrap risky code with ErrorHandler::call for safer debugging.
composer require symfony/error-handler
use Symfony\Component\ErrorHandler\Debug;
Debug::enable();
$data = \Symfony\Component\ErrorHandler\ErrorHandler::call(function () {
return json_decode(file_get_contents('data.json'));
});
AppServiceProvider or bootstrap/app.php to enable globally.artisan commands:
use Symfony\Component\ErrorHandler\ErrorHandler;
ErrorHandler::register();
Replace Laravel’s @ operator or try-catch blocks with ErrorHandler::call():
// Before: Silenced errors (risky)
$fileContent = @file_get_contents('config.json');
// After: Exceptions for all errors
$data = ErrorHandler::call(function () {
return file_get_contents('config.json');
});
Enable in AppServiceProvider:
public function boot()
{
if (app()->environment('local')) {
Debug::enable();
}
}
Override default error pages (e.g., for APIs):
use Symfony\Component\ErrorHandler\HtmlErrorRenderer;
HtmlErrorRenderer::setTemplate(__DIR__.'/custom-error-template.html.php');
Sanitize sensitive data in stack traces:
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
HtmlErrorRenderer::setTemplate(__DIR__.'/production-error-template.html.php');
// Template masks API keys, passwords, etc.
Wrap queue jobs to ensure failures propagate:
use Illuminate\Bus\Queueable;
use Symfony\Component\ErrorHandler\ErrorHandler;
class ProcessPayment implements Queueable
{
public function handle()
{
return ErrorHandler::call(function () {
// Payment logic here
});
}
}
Enable DebugClassLoader for class resolution problems:
use Symfony\Component\ErrorHandler\DebugClassLoader;
DebugClassLoader::enable();
Create middleware to wrap requests:
namespace App\Http\Middleware;
use Closure;
use Symfony\Component\ErrorHandler\ErrorHandler;
class StandardizeErrors
{
public function handle($request, Closure $next)
{
return ErrorHandler::call(function () use ($request, $next) {
return $next($request);
});
}
}
Convert exceptions to JSON responses:
use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\HttpFoundation\JsonResponse;
public function handle(Exception $e)
{
$flattened = FlattenException::createFromThrowable($e);
return new JsonResponse([
'error' => $flattened->getMessage(),
'trace' => $flattened->getTraceAsString(),
], 500);
}
Force exceptions in tests:
public function testPaymentFailure()
{
$this->expectException(\RuntimeException::class);
ErrorHandler::call(function () {
// Simulate a failed payment
});
}
Debug Mode in Production
Debug::enable() in production can expose sensitive data.if (app()->environment('local')) {
Debug::enable();
}
Silenced Errors Still Matter
@ or ErrorHandler::call() doesn’t mean errors are ignored—ensure they’re logged.ErrorHandler::call(function () {
// Risky code
}, function ($error) {
\Log::error($error);
});
Custom Templates Override
Performance Overhead
ErrorHandler::call() adds minor overhead to every wrapped block.Deprecation Warnings
ErrorHandler::register(null, true); // Enable deprecation notices
Inspect Flattened Exceptions
Use FlattenException to debug:
$flattened = FlattenException::createFromThrowable($e);
dump($flattened->getMessage(), $flattened->getTrace());
Enable Verbose Error Output For CLI debugging:
Debug::enable(true); // Enable verbose mode
Log Unhandled Errors Catch and log errors globally:
ErrorHandler::register(function ($error) {
\Log::critical($error, ['exception' => $error]);
});
Debug Autoloading Issues
Use DebugClassLoader to trace class resolution:
DebugClassLoader::enable();
// Trigger an error in a missing class to see autoloading details
Custom Error Renderers
Extend HtmlErrorRenderer for tailored output:
class CustomErrorRenderer extends HtmlErrorRenderer
{
protected function renderException(ExceptionInterface $exception): string
{
// Custom logic
}
}
Custom Error Handlers Override default behavior:
ErrorHandler::register(function ($error) {
// Custom logic (e.g., send to Sentry, Slack)
});
Integrate with Laravel Events Dispatch events on errors:
ErrorHandler::register(function ($error) {
event(new \App\Events\ErrorOccurred($error));
});
Conditional Error Handling Route errors based on context:
ErrorHandler::call(function () {
// API logic
}, function ($error) {
if (app()->bound('http.request')) {
// Return JSON error
} else {
// Log and rethrow
}
});
Dynamic Template Selection Use middleware to set templates per route:
public function handle($request, Closure $next)
{
if ($request->is('api/*')) {
HtmlErrorRenderer::setTemplate(__DIR__.'/api-error-template.html.php');
}
return $next($request);
}
Error Metrics Track error rates with Prometheus:
ErrorHandler::register(function () {
\Prometheus\CollectorRegistry::default()->getOrRegisterCounter(
'app_errors_total',
'Total errors',
['type']
)->inc();
});
How can I help you explore Laravel packages today?