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 Input Bundle Laravel Package

sfmok/request-input-bundle

A PHP package that bundles convenient request input helpers for retrieving, validating, and transforming incoming request data through clean, typed accessors. It reduces controller boilerplate and keeps input handling consistent, predictable, and safe across your application.

View on GitHub
Deep Wiki
Context7

Getting Started

sfmok/request-input-bundle is a Symfony bundle, not a Laravel package — it ships no service provider, no auto-discovery, and nothing to php artisan vendor:publish. What it gives you is an argument resolver that turns raw request data into typed input objects, so a controller action can receive a hydrated DTO instead of reaching into $request->query/$request->request by hand. Treat it as a focused alternative to hand-rolled hydration plus a validator call.

First steps, in order:

  1. Check the version constraint before anything else. v2.0.0 adds Symfony 8 support and was published as a major, which in practice means the component constraints changed. Laravel 11/12 pull in Symfony 7 components, so ^2.0 will not resolve in a standard Laravel app. Install ^1.2 unless you are on a Symfony 8 / PHP 8.4 runtime.
  2. Read the attribute class and the value resolver first, then the README. The README shows the happy path; the resolver shows the coercion rules (string → int, empty string → null, repeated query params → array), which is where the surprises live.
  3. Read the test fixtures. They are the most reliable documentation of supported shapes — scalars, nested objects, collections, nullable fields.

A good first use case is a read-only, filter-heavy endpoint (search, index, reporting) where you currently do fifteen $request->input(...) calls with inline casts. Define one input object with typed public properties, bind it, and delete the casting block. Save write endpoints for later — they need error mapping (see Gotchas) before they're worth it.

Implementation Patterns

One input class per action, not per resource. These objects are request-shaped, not domain-shaped. SearchUsersInput with ?string $q, int $page, array $roles is fine; reusing it across create/update/index is how you end up with a class where half the properties are conditionally required.

Don't import it into controllers directly if you can avoid it. In a Laravel codebase the cleanest wiring is a thin adapter layer: a base FormRequest-like class or a middleware that (a) hydrates the input object, (b) runs Validator::make($input->toArray(), $rules), (c) throws ValidationException on failure, (d) rebinds the input into the container for the controller to type-hint. That keeps the vendor type out of your action signatures and makes swapping the bundle out a one-file change.

Keep the bundle on the edge of the app. Flow: request → input object → command/action → domain. Pass $input->toArray() or explicit constructor args into the action; never let an input object reach a repository or an Eloquent model.

Pair with the Symfony Validator or Laravel's validator, not both. If you already have Laravel validation rules in FormRequest classes, mirror them as a rules() method on the input object and let the adapter call one validator. Two validation systems on the same payload is a debugging tax with no upside.

Nested input objects for structured payloads. A CreateOrderInput holding an AddressInput and a Collection<LineItemInput> beats flattening into a dozen top-level fields — the nesting is where typed hydration pays for itself, and it's also where the bundle is most likely to need a custom denormalizer (see Gotchas).

Test the hydration, not just the endpoint. A small unit test that constructs a Request with a given query/body and asserts the resulting input object is cheap, fast, and catches almost every regression you'll actually hit.

Gotchas and Tips

  • v2.0.0 is a compatibility release, not a feature release. The only change is Symfony 8 support. If you're on Laravel, this is a non-upgrade: stay on ^1.2 until Laravel's Symfony component floor moves. Do not let Dependabot open the PR.
  • PHP floor moved with Symfony 8. Symfony 8 requires PHP 8.4+. If your CI matrix includes 8.2/8.3, ^2.0 will fail install before it fails tests — check platform.php in composer.json.
  • No Laravel auto-discovery means composer require is the easy half. You must register the resolver yourself. If you only ever get "unresolvable dependency" / "Target class does not exist" errors on the input class, the resolver isn't wired — that's the wiring, not your DTO.
  • Empty strings are not null. HTML forms and query strings send "" for cleared fields; a non-nullable ?int $page will blow up or coerce to 0 depending on the resolver path. Normalize an empty string to null in the input object's constructor or accept ?string and cast downstream.
  • Repeated query params (?tag=a&tag=b) arrive as arrays only sometimes. Test this explicitly if you accept list filters; a single ?tag=a may hydrate as a scalar and fail on an array type.
  • Error handling is Symfony-flavoured. The bundle throws Symfony exceptions; Laravel's exception handler won't convert them to a 422 with an errors bag or a redirect-back-with-input for web routes. Wrap the hydration call and rethrow as ValidationException::withMessages(...) unless you're building a JSON-only API.
  • File uploads and multipart bodies are the wrong tool for this. UploadedFile handling lives in FileBag; keep those endpoints on a normal FormRequest.
  • Debugging tip: when hydration silently yields null or defaults, dd($request->getContent(), $request->query->all()) before the resolver runs. The failure mode is usually "the key isn't where the resolver looks" (query vs body vs attributes), not a type problem.
  • Extension points worth knowing exist: the value resolver itself, and any denormalizer/normalizer layer for custom types. Register a resolver for your own scalar objects — value objects, UUIDs, backed enums, CarbonImmutable — rather than teaching each input class to parse them in a constructor. That is the one place this bundle is genuinely nicer than a FormRequest.
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