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

Teapot Laravel Package

shrikeh/teapot

Teapot is a PHP library for building and manipulating HAL+JSON hypermedia APIs. It offers straightforward classes for resources, links and collections, making it easy to model and serialise RESTful responses that follow the HAL specification.

Deep Wiki
Context7

Getting Started

shrikeh/teapot is a constants-only package. There is no service provider, no facade, no config file, and nothing to publish. Installation is the entire setup:

composer require shrikeh/teapot

Look first at the main Teapot\StatusCode class in vendor/shrikeh/teapot/src/ and the README's naming table. The convention is HTTP_* (e.g. HTTP_OK, HTTP_CREATED, HTTP_NOT_FOUND, HTTP_I_AM_A_TEAPOT). Grouped classes (WebDAV, RFC-specific sets) exist in some versions for codes that don't live in the core HTTP/1.1 set — check which ones your installed version actually ships before referencing them.

The first use case is replacing magic numbers in a controller:

use Teapot\StatusCode;

public function store(StoreOrderRequest $request)
{
    $order = Order::create($request->validated());

    return response()->json($order, StatusCode::HTTP_CREATED);
}

Before going further, run one honest check: in Laravel you already have Symfony\Component\HttpFoundation\Response::HTTP_CREATED (inherited by Illuminate\Http\Response). Teapot buys you a second vocabulary for the same integers. For a greenfield Laravel app, the dependency rarely pays for itself; it earns its place mainly when you want a framework-neutral vocabulary, codes Symfony's list doesn't cover, or a consistent naming scheme across a mixed PHP codebase.

Implementation Patterns

Controllers and API responses. Use constants wherever a status integer would otherwise appear: response()->json($data, StatusCode::HTTP_OK), response()->noContent() (204 needs no constant), response($payload, StatusCode::HTTP_ACCEPTED).

Aborts and exceptions. abort() and HttpException both take an int, so constants pass through cleanly:

abort(StatusCode::HTTP_FORBIDDEN, 'Not your order.');
throw new HttpException(StatusCode::HTTP_CONFLICT, 'Already shipped.');

Exception handler. In bootstrap/app.php (Laravel 11+) or App\Exceptions\Handler, use constants in render/register callbacks and in respond() mappings so the status-code intent is readable:

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (OrderLocked $e) {
        return response()->json(['error' => $e->getMessage()], StatusCode::HTTP_LOCKED);
    });
})

Validation responses. Override failedValidation() in a FormRequest and return StatusCode::HTTP_UNPROCESSABLE_ENTITY. This is one of the few places where the named constant genuinely reads better than 422.

Middleware. Short-circuit with return response()->json(..., StatusCode::HTTP_TOO_MANY_REQUESTS); the constant makes rate-limit and maintenance-mode middleware self-documenting.

API Resources. Status codes are set at the response layer, not inside the resource: (new OrderResource($order))->response()->setStatusCode(StatusCode::HTTP_CREATED).

Tests. Use the same constants in assertions to keep test intent aligned with production code: $response->assertStatus(StatusCode::HTTP_NO_CONTENT). This is also a cheap way to catch accidental constant renames on upgrade.

Aliasing for brevity. If StatusCode:: feels noisy, alias the class at the top of the file: use Teapot\StatusCode as Http; then Http::HTTP_OK. Avoid use const imports — they scatter the vocabulary and make grep harder.

Anti-corruption layer. If you want type safety, wrap Teapot in a PHP 8.1 backed enum (enum HttpStatus: int { case Ok = StatusCode::HTTP_OK; ... }) and use the enum in your domain. This also makes it trivial to drop Teapot later without touching call sites.

Gotchas and Tips

It duplicates what Laravel already ships. Symfony\Component\HttpFoundation\Response defines every common HTTP_* constant, and Laravel's HTTP layer inherits them. Adding Teapot means two constants with the same value in the same codebase. Pick one vocabulary per project and enforce it in review; mixed usage is the most likely failure mode.

Constants are integers — there is no type safety. A class constant cannot be type-hinted, cannot be exhaustively matched, and gives you nothing at runtime. If you need validation ("is this a real status code?"), a constants library won't help; build a set or enum.

Naming is not perfectly uniform. Codes can appear in multiple group classes (core, WebDAV, RFC-specific) with the same value under different names. Reference one canonical class per code to avoid drift, and confirm the exact class/constant exists in your installed version — the set of grouped classes has changed across releases.

Low-activity dependency. Last release is 2024-10-07 and the package is small. Pin the version, read the changelog before upgrades, and check the PHP constraint against your runtime. Because it is constants-only, the blast radius of removal is small — which is exactly why you shouldn't let it spread into deep domain code.

No side effects, no autoload surprises. Class constants are resolved through the autoloader, so opcache/preloading and Laravel Octane are unaffected. There is nothing to warm or cache.

Don't mirror these as global define() constants. Class constants avoid global-namespace collisions; defining HTTP_OK globally reintroduces exactly the problem the package solves.

abort() and HttpException accept ints, not constants. That's fine — pass the constant directly. Don't wrap it in (int) or a helper; it only obscures intent.

No meaningful extension points. The classes are constant containers; subclassing them is pointless. Extend by wrapping (your own enum or HttpStatus class), not by inheriting.

Debugging tip. When a response code looks wrong, search for the numeric literal as well as the constant name — a single stray 201 or 422 in a controller or test is the usual culprit, and Teapot cannot protect you from literals you didn't replace.

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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core