rollandrock/param-converter-bundle
A Symfony bundle that provides parameter converters for turning request data into objects or typed values with configurable conversion logic, helping keep controllers clean, reusable, and easier to test.
Confirm the framework first. Despite the Laravel framing, this is a Symfony bundle — Bundle suffix, and "param converter" is a Symfony/SensioFrameworkExtraBundle concept (ParamConverterInterface, the request.param_converter service tag). If your stack is Laravel, this package is not applicable; the nearest equivalents are route model binding, Route::bind(), and FormRequests. Don't composer require it into a Laravel app — it will pull symfony/http-kernel and fight the framework for no benefit.
If you are on Symfony, the minimal path:
composer require rollandrock/param-converter-bundle
// config/bundles.php
return [
// ...
RollandRock\ParamConverterBundle\ParamConverterBundle::class => ['all' => true],
];
(Verify the exact FQCN and casing — with zero adopters, the README is the only source of truth.)
Where to look first, in order:
composer.json in the repo — check require for symfony/framework-bundle, sensio/framework-extra-bundle, and the PHP/Symfony version constraints. This tells you whether the bundle targets an era of Symfony you actually run.src/ for classes implementing ParamConverterInterface, and a DependencyInjection/*Extension.php for the config tree.README.md for the tag names and service registration snippet.tests/ — if it's absent or thin, treat the package as read-before-use and budget time to write your own coverage.The one command that matters after install:
bin/console debug:container --tag=request.param_converter
This lists every registered converter and its priority. If the tag is empty, the bundle installed but wired nothing (or wired to a different tag) — resolve that before writing a single line against it. Follow with:
bin/console config:dump-reference param_converter
First use case: a route parameter needs to become a typed object without boilerplate in the controller.
#[Route('/invoice/{invoice}', methods: ['GET'])]
public function show(Invoice $invoice): Response
{
// $invoice is already resolved, or a 404 was thrown
}
Or the annotation style if the bundle targets older Symfony:
/**
* @ParamConverter("invoice", class="App\Entity\Invoice")
*/
supports() returns true only for a specific class (entity, enum, UUID value object, DTO), with the resolution logic in apply(). Compose several small converters rather than one branching mega-converter — priority ordering is what arbitrates between them, and a monolith makes that ordering irrelevant-but-opaque.priority attribute on the tag (default 0). The Doctrine ORM converter usually competes for entity classes; if you want your converter to intercept, give it a priority above the Doctrine one and confirm with debug:container.false, don't throw, on "not mine." supports() should be cheap and side-effect free — it runs for every parameter of every controller. apply() should return false when the parameter is already an instance of the target, so the chain falls through cleanly to the next converter.NotFoundHttpException. "Malformed id" is BadRequestHttpException or a validation failure. A converter that throws 404 on a malformed UUID hides client bugs behind a misleading status code and makes support tickets unreadable.$request->attributes does nothing about constraints. Follow with #[Assert]/Validator or #[MapRequestPayload]; don't assume the converter validated the input.$request->query->all(), hydrate via constructor or the Serializer, $request->attributes->set($param, $dto), return true. Keep the hydration strict — unknown keys should error, not be silently dropped.false without exploding); not-found. Those are the failure modes that otherwise only surface in production.Workflow: inventory the tag → write one controller action and assert resolution → hit the route with a deliberately bad id to confirm the status code is the one you intended.
composer.json, and add a smoke test that exercises the converter so an upstream drift fails CI instead of production.composer show -a rollandrock/param-converter-bundle and check the tag history before trusting any constraint.ParamConverterInterface, they may not auto-convert at all on a current install. Check with composer why sensio/framework-extra-bundle before debugging your own code.request.param_converter. A bundle wired to a slightly different tag installs cleanly and does absolutely nothing. This is the single most common "it doesn't work" cause with param converters.true means the higher priority wins and the other never runs — no error, no log. Inspect with debug:container --tag=request.param_converter --show-private.bin/console cache:clear; a stale cache produces "class not found" or mysteriously missing converters that look like bugs in the package.$request->attributes->all() at the top of the controller to see whether the converter ran at all; the profiler's request panel shows the kernel.controller listener chain and where in it the conversion happens.ParamConverterInterface implementation in app code (or an ArgumentResolver on 6.2+) rather than forking this bundle. The interface is tiny, app-local converters are trivially testable, and you avoid owning a dependency with no maintainer signal. Fork only if you specifically need this bundle's converter semantics and can't reproduce them in ~40 lines.How can I help you explore Laravel packages today?