Skip to content

Commit 3725279

Browse files
tonivdvGuilhemN
authored andcommitted
fix route generator not ignoring body param converters (#1934)
* fix route generator not ignoring body param converters When fetching a list of function parameters from a controller action for use as URL parameters, check for the @ParamConverter annotation. If a parameter has the annotation with the "fos_rest.request_body" converter, then ignore it and do not include it in the list of parameters (thus removing it from the URL). This allows automatic route generation and ParamConverter to co-exist, as otherwise a parameter that is expected to be derived from the body would also be included as a URL parameter, requiring the developer to manually specify the route. fixes #1198 * fix some small things after review * simplify FQN * fix cs * revert global namespace FQN simplification
1 parent 5e38509 commit 3725279

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

Routing/Loader/Reader/RestActionReader.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
use Doctrine\Common\Annotations\Reader;
1515
use FOS\RestBundle\Controller\Annotations\Route as RouteAnnotation;
1616
use FOS\RestBundle\Inflector\InflectorInterface;
17+
use FOS\RestBundle\Request\ParamFetcherInterface;
1718
use FOS\RestBundle\Request\ParamReaderInterface;
1819
use FOS\RestBundle\Routing\RestRouteCollection;
1920
use Psr\Http\Message\MessageInterface;
21+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
22+
use Symfony\Component\HttpFoundation\Request;
2023
use Symfony\Component\Routing\Route;
24+
use Symfony\Component\Validator\ConstraintViolationListInterface;
2125

2226
/**
2327
* REST controller actions reader.
@@ -475,12 +479,23 @@ private function getMethodArguments(\ReflectionMethod $method)
475479
// ignore all query params
476480
$params = $this->paramReader->getParamsFromMethod($method);
477481

482+
// check if a parameter is coming from the request body
483+
$ignoreParameters = [];
484+
if (class_exists(ParamConverter::class)) {
485+
$ignoreParameters = array_map(function ($annotation) {
486+
return
487+
$annotation instanceof ParamConverter &&
488+
'fos_rest.request_body' === $annotation->getConverter()
489+
? $annotation->getName() : null;
490+
}, $this->annotationReader->getMethodAnnotations($method));
491+
}
492+
478493
// ignore several type hinted arguments
479494
$ignoreClasses = [
480-
\Symfony\Component\HttpFoundation\Request::class,
481-
\FOS\RestBundle\Request\ParamFetcherInterface::class,
482-
\Symfony\Component\Validator\ConstraintViolationListInterface::class,
483-
\Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter::class,
495+
Request::class,
496+
ParamFetcherInterface::class,
497+
ConstraintViolationListInterface::class,
498+
ParamConverter::class,
484499
MessageInterface::class,
485500
];
486501

@@ -500,6 +515,10 @@ private function getMethodArguments(\ReflectionMethod $method)
500515
}
501516
}
502517

518+
if (in_array($argument->getName(), $ignoreParameters, true)) {
519+
continue;
520+
}
521+
503522
$arguments[] = $argument;
504523
}
505524

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace FOS\RestBundle\Tests\Fixtures\Controller;
4+
5+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
6+
7+
/**
8+
* @author Toni Van de Voorde <[email protected]>
9+
*/
10+
class ParamConverterController
11+
{
12+
/**
13+
* @ParamConverter("something", converter="fos_rest.request_body")
14+
*
15+
* @param Something $something
16+
*/
17+
public function postSomethingAction(Something $something)
18+
{
19+
}
20+
}
21+
22+
final class Something
23+
{
24+
public $id;
25+
}

Tests/Routing/Loader/RestRouteLoaderTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,17 @@ public function testRequestTypeHintsIgnoredCorrectly()
370370
$this->assertEquals('/articles/{id}.{_format}', $collection->get('post_article')->getPath());
371371
}
372372

373+
/**
374+
* @see https://github.com/FriendsOfSymfony/FOSRestBundle/issues/1198
375+
*/
376+
public function testParamConverterIsIgnoredInRouteGenerationCorrectly()
377+
{
378+
$collection = $this->loadFromControllerFixture('ParamConverterController');
379+
380+
$this->assertNotNull($collection->get('post_something'), 'route for "post_something" does not exist');
381+
$this->assertSame('/somethings.{_format}', $collection->get('post_something')->getPath());
382+
}
383+
373384
/**
374385
* Load routes collection from fixture class under Tests\Fixtures directory.
375386
*

0 commit comments

Comments
 (0)