Back to Snippets

Laravel Non-Fatal Exception Pattern

🐘 Laravel

Pattern for using custom exceptions to return structured responses without halting execution.

🏷️ php
PHP Laravel Exception Handling Patterns

Custom Exception Class

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class InvalidUserStatusException extends Exception
{
    protected $message = 'User status is invalid for this operation.';

    public function render(Request $request): Response
    {
        if ($request->expectsJson()) {
            return response()->json([
                'error' => 'Invalid User Status',
                'message' => $this->getMessage()
            ], 422);
        }

        return response()->view('errors.invalid-user-status', [], 422);
    }
}

Usage in Service or Controller

<?php

namespace App\Services;

use App\Exceptions\InvalidUserStatusException;
use App\Models\User;

class UserService
{
    public function activateUser(User $user)
    {
        if ($user->status !== 'pending') {
            throw new InvalidUserStatusException();
        }

        $user->status = 'active';
        $user->save();

        return $user;
    }
}

This pattern allows you to avoid lots of propagating if statements, early returns, or repeated response handling in your controller. You can focus on the main flow and cleanly exit out of “bad” states with a clear, centralised exception response.