Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Http Exception Laravel Package

havvg/http-exception

havvg/http-exception provides lightweight, framework-agnostic HTTP exception classes for PHP, covering common 4xx and 5xx status codes with reason phrases. Throw typed exceptions to signal HTTP errors and map them cleanly to responses or middleware.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and inspect before you write code.

composer require havvg/http-exception

Then open vendor/havvg/http-exception/src/ and read two files first:

  1. The base HttpException class — this is where the status code and headers live.
  2. HttpExceptionInterface — the contract (getStatusCode() / getHeaders()) you should catch against rather than catching concrete classes.

The package is deliberately tiny: one exception class per HTTP status code (NotFoundException, BadRequestException, MethodNotAllowedException, etc.), each pre-seeded with its numeric status and a sensible default message. There is no service provider, no config file, and no framework coupling.

First use case — replace magic status codes in a controller:

use Havvg\HttpException\NotFoundException;

public function show(int $id): User
{
    $user = User::find($id);

    if (! $user) {
        throw new NotFoundException("User {$id} does not exist.");
    }

    return $user;
}

Before adopting it, confirm two things: the php constraint in composer.json (this package is old — if it pins ~5.3 you will need a fork or --ignore-platform-reqs on PHP 8), and whether you intend to use it in Laravel at all. Laravel ships abort(404) and Symfony\Component\HttpKernel\Exception\HttpException, which cover the same ground. The value here is typed, self-documenting exceptions thrown from the domain layer rather than string-based abort() calls — not framework integration.

Implementation Patterns

Throw low, render high. Let services and actions throw the concrete exception; let a single boundary (controller exception handler, middleware, or console kernel) convert it into a response. This keeps HTTP semantics out of your domain code's return types while still being explicit.

Catch the interface, not the class. Any generic handler should type-hint HttpExceptionInterface so new status codes you add later are handled automatically:

try {
    $action->execute($request);
} catch (HttpExceptionInterface $e) {
    return response($e->getMessage(), $e->getStatusCode(), $e->getHeaders());
}

Wire it into Laravel's render pipeline. In Laravel 11+, register renderable closures in bootstrap/app.php; on 10 and below, override render() in app/Exceptions/Handler.php:

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (HttpExceptionInterface $e) {
        return response($e->getMessage(), $e->getStatusCode(), $e->getHeaders());
    });
})

Extend for statuses the package is missing. Codes added to the RFC after the package's last release (429, 451, 422 with a specific body shape) are usually absent. Subclass the base and pin the code in the constructor:

class TooManyRequestsException extends HttpException
{
    public function __construct(string $message = 'Too Many Requests', array $headers = [])
    {
        parent::__construct(429, $message, $headers);
    }
}

Pass headers through the constructor. MethodNotAllowedException and UnauthorizedException are far more useful when you attach Allow: GET, POST or WWW-Authenticate: Bearer — carry them on the exception rather than reconstructing them at the render site.

Use the hierarchy for coarse fallbacks. If the package groups 4xx/5xx under intermediate base classes (as most of these collections do), you can write catch (ClientErrorException $e) to apply one policy — e.g. log at warning — and catch (HttpExceptionInterface $e) for server errors that should log at error with a stack trace.

Gotchas and Tips

Laravel will render these as 500s by default. The framework's handler special-cases Symfony\...\HttpExceptionInterface. An exception implementing only the Havvg interface falls through to the generic 500 path with a rendered error page. Always add the render binding above — this is the single most likely reason your 404 becomes a 500 in production.

Version and PHP compatibility is the real risk. With 0 dependents and low stars, treat this as unmaintained. Check the composer.json constraints before adding it to an existing project; if it blocks a PHP 8 upgrade, fork it into your own namespace rather than pinning your runtime. The classes are ~10 lines each, so vendoring is cheap.

Namespace and autoloading. Older releases in this family use PSR-0 with underscores in the namespace. If composer dump-autoload doesn't resolve the class, look at the autoload block and the directory layout together — don't assume src/ maps to Havvg\HttpException.

Don't let messages leak. These exceptions carry human-readable messages that are convenient in development and dangerous in production. Distinguish "safe to render" (validation, not-found) from "log only" (5xx), and strip messages for the 500 range.

Status codes are constructor arguments, not class constants. There's typically no NotFoundException::STATUS_CODE. If you need the number without instantiating, that's a sign you should be passing the exception around, not the integer.

Testing is trivial and worth doing. $this->expectException(NotFoundException::class) plus a status-code assertion on a caught instance is enough. If you build a render test, assert the response status and headers — header handling is the most common silent regression when you swap out the handler.

Consider whether you need it at all. For a Laravel app, abort(404) plus a small custom exception hierarchy in app/Exceptions/ gives you the same typed-exception ergonomics with zero dependency risk and full framework integration. Adopt this package when you want a ready-made, framework-agnostic set of classes — for a shared library, a Slim/Silex service, or a codebase that already speaks in these exception names.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource