sandronimus/nelmio-form-get-parameter-plugin-bundle
A Symfony bundle that plugs into NelmioApiDocBundle to support form GET parameters in API documentation, helping you describe query-string inputs accurately. Small, focused integration for projects already using Nelmio; low adoption and minimal community activity, so evaluate fit and maintenance bef...
The package is a small Symfony bundle that plugs into NelmioApiDocBundle to translate Symfony Form fields into documented query parameters for GET endpoints. It is not auto-configured by Symfony Flex, and with effectively zero adoption you should treat it as "vendor this code" rather than "install and forget."
Minimal path:
Install the dependency alongside a working NelmioApiDocBundle setup:
composer require sandronimus/nelmio-form-get-parameter-plugin-bundle
Register the bundle manually in config/bundles.php (there is no Flex recipe):
Sandronimus\NelmioFormGetParameterPluginBundle\NelmioFormGetParameterPluginBundle::class => ['all' => true],
Open the package source before wiring anything. Look in vendor/sandronimus/nelmio-form-get-parameter-plugin-bundle/src/ first for:
DependencyInjection/ for the service definition and tag name,Resources/config/services.* for how the plugin is registered.If the service is not tagged, add it yourself:
# config/services.yaml
services:
Sandronimus\NelmioFormGetParameterPluginBundle\Plugin\FormGetParameterPlugin:
tags:
- { name: nelmio_api_doc.route_describer, priority: 0 }
First use case: a search/filter endpoint that takes a Symfony form via GET. Define the form, inject it into the controller with #[Model] / #[ApiDoc], and confirm the dump output:
bin/console nelmio:apidoc:dump --format=json | jq '.paths | keys'
You should now see the form's fields represented as in: query parameters rather than a request body.
If the README is empty or the bundle fails to load, copy the plugin class straight into src/OpenApi/ in your app and register it as a tagged service — for a 0-star package, vendoring the ~100 lines of a route describer is usually lower risk than depending on it.
Form-driven query documentation. The intended workflow is: controller receives a form type, form type declares method => 'GET' or is used by a GET route, and the plugin converts each FormType field into an OpenAPI query parameter using the field's label, required, and constraints. Keep the form as the single source of truth — do not also list the parameters manually in @OA\Parameter annotations, or you will get duplicates.
Controller-level wiring. Typical shape:
#[Route('/search', methods: ['GET'])]
#[Model(type: SearchFormType::class, groups: ['api'])]
public function search(Request $request): Response
{
$form = $this->createForm(SearchFormType::class, null, ['method' => 'GET']);
$form->handleRequest($request);
// ...
}
Register the plugin so it runs on the route describer phase, before Nelmio generates the operation. If your Nelmio version supports both, prefer route_describer over model_describer — the parameters belong to the operation, not to a reusable schema.
Per-area integration. If you scope Nelmio with areas (e.g. internal, public), enable the plugin only where it matters. Restricting by area in config/packages/nelmio_api_doc.yaml avoids polluting internal docs with public-form query params:
nelmio_api_doc:
areas:
public:
path_patterns: ['^/api']
internal:
path_patterns: ['^/internal']
Form inheritance and composition. The plugin typically walks FormType::buildForm; this means embedded types and CollectionType fields are the weak spot. If you have a shared BaseFilterType, either flatten it in the concrete type or verify the plugin recurses into children (read the source). A safe pattern is to define one thin form per endpoint that explicitly declares the fields you want documented, rather than one giant reusable form.
Combination with a manual OpenAPI attribute. When you need a parameter the form cannot express (e.g., page, cursor, sort), add it as a normal #[OA\Parameter] on the controller. Keep the split clean: form fields via the plugin, pagination/sorting via attributes. Document the split in the controller docblock so the next developer knows why half the params appear twice in the source.
Testing in CI. Add a smoke test that dumps the spec and asserts the expected parameters exist, so a Nelmio upgrade that silently breaks the plugin is caught:
bin/console nelmio:apidoc:dump --format=json > /tmp/spec.json
grep -q '"in":"query"' /tmp/spec.json
composer.json and vendor the plugin class if you depend on it for a public API contract.method mismatch. Forms default to POST. Setting the route to GET is not enough — Symfony's form component still resolves to POST unless you set method => 'GET', and the plugin may key off that. Double-check the form option in the controller, not in the type.bin/console cache:clear and, if you use a spec cache warmer, delete var/cache/*/nelmio.#[Model] on a form and an @OA\Parameter with the same name, OpenAPI consumers will show duplicates. Remove the annotation and let the plugin own it, or strip the plugin from that route.required maps loosely to OpenAPI required. A field marked required in the form will be documented as a required query param, which is often wrong for filters. Override per-field by setting required => false and adding a validator constraint instead.ChoiceType fields will render as string with no enum unless the plugin is smart about it; verify in the dumped spec. If not, add an #[OA\Parameter] with schema: new OA\Schema(type: 'string', enum: [...]) to override.vendor/nelmio/api-doc-bundle/ which tag your installed version actually scans for, and update services.yaml accordingly. A silently unregistered plugin produces no errors — just missing parameters.bin/console nelmio:apidoc:dump --format=json | jq '.paths["/search"].get.parameters'. If parameters are missing, add a temporary dump() inside the plugin's describe() method and check whether it is invoked at all; if not, the tag/registration is wrong.FormType introspection (getBlockPrefix, field mapped flag, nested all() children) rather than fighting the bundle to support a form shape it never anticipated.Api\*FormType classes.How can I help you explore Laravel packages today?