dosfarma/exceptions
Lightweight Laravel/PHP exception utilities for standardizing, wrapping, and handling application errors. Helps you define consistent exception types and messages across your codebase, improving error clarity, debugging, and maintainability with minimal setup.
Installation
composer require dosfarma/exceptions
Add the service provider to config/app.php:
'providers' => [
// ...
Dosfarma\Exceptions\ExceptionsServiceProvider::class,
],
Basic Usage Define a custom exception:
use Dosfarma\Exceptions\ApiException;
class UserNotFoundException extends ApiException
{
public function __construct()
{
parent::__construct('User not found', 404);
}
}
First Use Case Throw the exception in a controller:
public function show($id)
{
$user = User::find($id);
if (!$user) {
throw new UserNotFoundException();
}
return $user;
}
Centralized Exception Handling
Override App\Exceptions\Handler to format exceptions:
public function render($request, Throwable $exception)
{
if ($exception instanceof \Dosfarma\Exceptions\ApiException) {
return response()->json([
'error' => $exception->getMessage(),
'code' => $exception->getCode(),
], $exception->getCode());
}
return parent::render($request, $exception);
}
Structured Error Responses
Extend ApiException for consistent payloads:
class ValidationException extends ApiException
{
public function __construct(array $errors)
{
parent::__construct('Validation failed', 422, [
'errors' => $errors,
]);
}
}
Middleware Integration Use middleware to log exceptions:
namespace App\Http\Middleware;
use Dosfarma\Exceptions\ApiException;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class LogExceptions
{
public function handle(Request $request, Closure $next)
{
try {
return $next($request);
} catch (ApiException $e) {
\Log::error($e->getMessage(), ['exception' => $e]);
throw $e;
}
}
}
API Resource Integration Return exceptions as JSON responses:
public function destroy($id)
{
$user = User::findOrFail($id);
$user->delete();
return response()->json(null, 204);
}
Inconsistent HTTP Codes
Ensure all custom exceptions extend ApiException and define proper HTTP status codes (e.g., 404, 400, 500).
Overriding Default Behavior
If extending App\Exceptions\Handler, ensure the render method doesn’t swallow ApiException instances unintentionally.
Missing Error Details in Production Avoid exposing sensitive data in exception messages or payloads. Use environment checks:
if (app()->environment('local')) {
return response()->json(['error' => $exception->getMessage()], 500);
}
Log Unhandled Exceptions
Add a fallback in App\Exceptions\Handler:
public function report(Throwable $exception)
{
if ($exception instanceof \Dosfarma\Exceptions\ApiException) {
\Log::error('API Exception: ' . $exception->getMessage());
}
}
Check Exception Payloads
Use dd() to inspect exception data:
try {
// ...
} catch (ApiException $e) {
dd($e->getData()); // Inspect payload structure
}
Custom Exception Classes
Extend ApiException for domain-specific errors:
class PaymentFailedException extends ApiException
{
public function __construct(string $message, array $details = [])
{
parent::__construct($message, 402, $details);
}
}
Dynamic Error Responses Use exception data to customize responses:
public function render($request, PaymentFailedException $e)
{
return response()->json([
'error' => $e->getMessage(),
'details' => $e->getData(),
'suggestions' => ['Retry payment', 'Contact support'],
], 402);
}
Localization Support Add language-specific messages:
class UserNotFoundException extends ApiException
{
public function __construct()
{
$message = __('exceptions.user_not_found');
parent::__construct($message, 404);
}
}
Testing Exceptions Mock exceptions in tests:
$this->expectException(UserNotFoundException::class);
$this->expectExceptionCode(404);
How can I help you explore Laravel packages today?