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

Request Bundle Laravel Package

jrm/request-bundle

jrm/request-bundle is a Symfony bundle that streamlines HTTP request handling, giving you a structured way to validate incoming data, map parameters to typed objects, and keep controllers thin. Drop-in integration and sensible defaults make it easy to adopt in existing projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Caveat before step one: jrm/request-bundle is a Symfony bundle, not a Laravel package. Its composer manifest pulls Symfony HTTP-kernel/DI components, and its value comes from Symfony's bundle boot + argument-resolver machinery. A Laravel app will not execute that boot logic, so composer require jrm/request-bundle in a Laravel project gets you a dependency, not a feature. Read this as "what it does, and how the pattern maps to Laravel" rather than an install-and-go guide.

New in 0.3.3 — check your Symfony version first. The release is a compatibility narrowing: Symfony 7.2 and higher only. Earlier lines supported 6.4/7.0/7.1; 0.3.3 does not. Before anything else run composer show jrm/request-bundle --all and read the require block, then composer why-not jrm/request-bundle 0.3.3 if resolution fails. This matters even for a Laravel app: Illuminate pins Symfony components transitively, so Laravel 10 (Symfony 6.x components) will hard-conflict with this constraint, and anything else in your tree still holding a symfony/*: ^6.4 or ^7.0 floor can block the upgrade.

Minimal steps if you are in a Symfony 7.2+ app:

  1. composer require jrm/request-bundle (expect ^7.2 on symfony/http-kernel + friends; if you are on 7.1, stay on 0.3.2).
  2. Register it in config/bundles.php (Flex usually does this).
  3. Read the bundle README first, then DependencyInjection/*Extension.php and Resources/config/services.*.yaml — that is where the request factory / argument resolver is wired. Confirm whether the bundle expects you to configure a request class or type-hint a subclass.
  4. Create App\Http\AppRequest extends Symfony\Component\HttpFoundation\Request with your helpers (->user(), ->wantsJson(), ->inputOr($key, $default)).
  5. Type-hint AppRequest in a controller action where you previously had Request.

First meaningful use case: stop repeating $request->query->get(...) ?? $request->request->get(...) and JSON-detection boilerplate in every action. Put it on one custom request class and let the resolver inject it.

In Laravel the equivalent first step is not this bundle — it is php artisan make:request StoreOrderRequest (a FormRequest) or binding a Request subclass in a service provider via $this->app->bind(Request::class, AppRequest::class) with a factory. Start there before pulling a third-party abstraction.

Implementation Patterns

Subclass-and-type-hint. The core pattern the bundle enables: one AppRequest subclass per app (or per domain), injected by type-hint. Keep it thin — helpers that read from query, request, headers, files, or attributes. Don't put business logic in it; it is a transport object with ergonomics.

final class AppRequest extends Request
{
    public function user(): ?User { return $this->attributes->get('user'); }
    public function inputOr(string $key, mixed $default = null): mixed
    {
        return $this->request->get($key) ?? $this->query->get($key) ?? $default;
    }
}

Populate once, read everywhere. If the bundle provides a factory, populate attributes with the authenticated user, tenant id, and request id once in a listener/middleware, then read from the injected request in controllers, subscribers, and services. This is the pattern that actually saves lines of code day-to-day.

Hydrate a DTO from the request. Pair the custom request with a small DTO: StoreOrderData::fromRequest(AppRequest $r). Controllers become public function store(AppRequest $r, StoreOrderData $d). This is the closest analogue to Laravel's FormRequest::validated() and is worth copying even if you never install the bundle.

Testing. Because it extends Request, build instances with Request::create('/orders', 'POST', [...]) and pass them to the controller directly, or configure the test container's request factory. Do not mock Request — it is cheap to construct.

Laravel mapping, if you are porting the idea:

  • Custom request class → FormRequest for validation; a Request subclass + container binding for read helpers.
  • Argument resolver → Laravel already injects Illuminate\Http\Request into controller methods; override the binding to swap in your subclass.
  • Factory/listener population → a global middleware calling $request->merge([...]) or setting attributes via $request->attributes->set(...).

Gotchas and Tips

Ecosystem mismatch is the biggest one. Tiny download footprint, effectively zero dependents, and a release cadence driven by one maintainer bumping Symfony version floors rather than adding features — 0.3.3 is only a constraint change. You are the first production user. Pin the exact version, vendor it if you must, and budget for it being abandoned. For a Laravel codebase, the honest recommendation is: don't install it, copy the pattern.

0.3.3 is a silent breaking change, not a feature release. "Symfony 7.2 and higher only" means: (a) existing installs on Symfony 6.4/7.0/7.1 cannot upgrade without a framework upgrade first, and (b) the patch-style version number (0.3.3) hides that from composer update reflexes. Pin to 0.3.2 or 0.3.3 explicitly — never ^0.3 — and read the diff of composer.json between tags, since the release notes are a one-liner and the constraint is what actually changed. Also check whether the Symfony floor was raised only or whether transitive pins (e.g. symfony/http-foundation, symfony/dependency-injection) moved with it; a partial bump can leave you with a resolver from one minor and a request from another.

Argument-resolver ordering. In Symfony, custom ValueResolvers run in tag-priority order. If Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver fires first, you get the base Request, not your subclass, and the type-hint silently doesn't match — you get a 500 about an unresolvable argument or, worse, the wrong object. Check debug:container --tag=controller.argument_value_resolver and adjust priority. Symfony 7.2 shuffled several HttpKernel internals, so re-verify priorities after any Symfony minor bump, not just after bundle bumps.

Subclassing Request is a footgun in Symfony. HttpFoundation creates the request from globals via Request::createFromGlobals(), which returns a base Request. If you subclass, either the bundle provides a replacement factory or you must set it up yourself (Request::setFactory() historically, or overriding the service). Verify which the bundle does before assuming the type-hint works — and re-verify after a Symfony upgrade, because setFactory() behaviour has changed across majors.

Don't hold state on the request object. Requests are per-request; caching them in singletons or static properties leaks between requests in long-running workers (RoadRunner, Swoole, FrankenPHP). Same warning applies to Laravel Octane.

Config quirks. Symfony bundles usually expose config under a short alias (jrm_request:). Run bin/console config:dump-reference jrm_request — if the command errors, the bundle has no extension or the alias differs from the package name. Read *Extension::load() to find the real key. A bundle this small may well ship no extension at all, in which case there is nothing to configure and everything is service-definition override.

Debugging checklist. composer why symfony/http-kernel (what pulled the 7.2 floor?), bin/console debug:container AppRequest (is it a service?), debug:event-dispatcher (is a listener populating attributes?), and a dd($request::class) at the top of the action (is the resolver doing its job?). Nine times out of ten the issue is registration or version resolution, not logic.

Extension points worth knowing. The attributes bag is the safest place to stash cross-cutting data (user, tenant, request id) — it survives middleware, is not sent to the client, and is not confused with input. Reach for it before merge() or query->set().

Laravel equivalents to reach for instead: FormRequest for validation + authorization, Request::macro() for small helpers without a subclass, a global middleware for population, and $this->app->bind(...) if you truly need a custom Request class everywhere. All four are first-party, documented, won't fight your Symfony constraint set, and won't strand you on an unmaintained bundle.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource