skills/leeovery/claude-laravel/laravel-exceptions

laravel-exceptions

SKILL.md

Laravel Exceptions

Custom exceptions use static factory methods and implement HttpExceptionInterface.

Related guides:

  • Actions - Throwing exceptions in actions

Structure

<?php

declare(strict_types=1);

namespace App\Exceptions;

use App\Exceptions\Concerns\Httpable;
use App\Models\Order;
use Exception;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;

class OrderException extends Exception implements HttpExceptionInterface
{
    use Httpable;

    public static function notFound(string|int $orderId): self
    {
        return new self("Order {$orderId} not found.", 404);
    }

    public static function cannotCancelOrder(Order $order): self
    {
        return new self(
            "Order {$order->uuid} cannot be cancelled in its current state.",
            400
        );
    }

    public static function insufficientStock(string $productName): self
    {
        return new self(
            "Insufficient stock for product: {$productName}",
            422
        );
    }

    public static function paymentFailed(string $reason): self
    {
        return new self("Payment failed: {$reason}", 402);
    }
}

Httpable Concern

View full implementation →

Usage

Throwing Exceptions

// In actions
throw OrderException::notFound($orderId);
throw OrderException::cannotCancelOrder($order);
throw OrderException::insufficientStock($product->name);

With throw_unless/throw_if

class CancelOrderAction
{
    public function __invoke(Order $order): Order
    {
        throw_unless(
            $order->canBeCancelled(),
            OrderException::cannotCancelOrder($order)
        );

        // Continue with cancellation
    }
}

Guard Methods

class ProcessOrderAction
{
    public function __invoke(Order $order): void
    {
        $this->guard($order);

        // Process order
    }

    private function guard(Order $order): void
    {
        throw_unless(
            $order->isPending(),
            OrderException::cannotProcessOrder($order)
        );

        throw_unless(
            $order->hasItems(),
            OrderException::orderHasNoItems($order)
        );
    }
}

Key Patterns

1. Static Factory Methods

Named constructors for specific exceptions:

public static function notFound(string|int $orderId): self
{
    return new self("Order {$orderId} not found.", 404);
}

2. HTTP Status Codes

Pass status as second constructor parameter:

new self("Message", 404);  // Not Found
new self("Message", 400);  // Bad Request
new self("Message", 422);  // Unprocessable Entity
new self("Message", 403);  // Forbidden

3. Descriptive Messages

Include context in error messages:

"Order {$order->uuid} cannot be cancelled"
"Insufficient stock for product: {$productName}"

4. HttpExceptionInterface

Implement interface for automatic HTTP error responses:

class OrderException extends Exception implements HttpExceptionInterface
{
    use Httpable;
}

Common HTTP Status Codes

  • 400 - Bad Request (business rule violation)
  • 402 - Payment Required
  • 403 - Forbidden (authorization failed)
  • 404 - Not Found
  • 422 - Unprocessable Entity (validation failed)
  • 500 - Internal Server Error

Directory Structure

app/Exceptions/
├── OrderException.php
├── PaymentException.php
├── UserException.php
└── Concerns/
    └── Httpable.php

Summary

Exceptions should:

  • Use static factory methods
  • Implement HttpExceptionInterface
  • Include HTTP status codes
  • Have descriptive messages with context
  • Be named {Entity}Exception

Use for business rule violations and error conditions.

Weekly Installs
24
GitHub Stars
37
First Seen
Jan 24, 2026
Installed on
opencode19
codex18
gemini-cli18
cursor18
github-copilot15
claude-code15