I am new to Symfony (5.3) and would like to extend the RequestBodyParamConverter
(FOSRestBundle 3.0.5) to create a REST api. Using @ParamConverter
annotation with the RequestBodyParamConverter
works fine. However, I would like to create a custom converter, which does the exact same job as RequestBodyParamConverter
plus a little extra work.
My first guess was to simply extend RequestBodyParamConverter
and provide my custom subclass in the @ParamConverter
annotation. However, RequestBodyParamConverter
is defined as final
and thus cannot be extended...
Injecting RequestBodyParamConverter
/ fos_rest.request_body_converter
into a custom converter class (see example below) also fails because the service cannot be found. I assume this is because it is defined a private
?
So, my last idea was to create a RequestBodyParamConverter
inside my custom converter class. While this works, I am not sure if this is the right way to solve this problem. This way RequestBodyParamConverter
is created twice. This is nothing special of course, but is this the Symfony way to solve this or are there other solutions?
Example:
Inject RequestBodyParamConverter
in custom converter class
class MyParamConverter implements ParamConverterInterface {
protected $parentConverter;
public function __construct(ParamConverterInterface $parentConverter) {
$this->parentConverter = $parentConverter;
}
public function apply(Request $request, ParamConverter $configuration): bool {
doExtraWork();
return $this->parentConverter->apply(...);
}
}
// config/services.yaml
My\Project\MyParamConverter:
tags:
- { name: request.param_converter, converter: my_converter.request_body }
arguments:
# both fails since service is not found
$parentConverter: '@FOS\RestBundle\Request\RequestBodyParamConverter'
# OR
$parentConverter: '@fos_rest.request_body_converter'
Create RequestBodyParamConverter
in custom converter class
class MyParamConverter implements ParamConverterInterface {
protected $parentConverter;
public function __construct(...parameters necessary to create converter...) {
$this->parentConverter = new RequestBodyParamConverter(...);
}
...
}
Symfony provide a way to decorate a registered service
To use it you need the FOS service id registered in the container.
To get it you can use this command
symfony console debug:container --tag=request.param_converter
Retrieve the Service ID
of the service you want to override.
Then you can configure your service to decorate FOS one
My\Project\MyParamConverter:
decorates: 'TheIdOf_FOS_ParamConverterService'
arguments: [ '@My\Project\MyParamConverter.inner' ] # <-- this is the instance of fos service
Maybe you'll need to add the tags
to this declaration, I'm not sure.
Let me know if you're facing an error.