-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Added an ArgumentResolver with clean extension point #18308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,11 @@ | |
namespace Symfony\Component\HttpKernel\Controller; | ||
|
||
use Symfony\Component\HttpFoundation\Request; | ||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver; | ||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; | ||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver; | ||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver; | ||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; | ||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface; | ||
|
||
/** | ||
|
@@ -30,8 +35,13 @@ final class ArgumentResolver implements ArgumentResolverInterface | |
|
||
public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, array $argumentValueResolvers = array()) | ||
{ | ||
$this->argumentMetadataFactory = $argumentMetadataFactory; | ||
$this->argumentValueResolvers = $argumentValueResolvers; | ||
$this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory(); | ||
$this->argumentValueResolvers = $argumentValueResolvers ?: array( | ||
new RequestAttributeValueResolver(), | ||
new RequestValueResolver(), | ||
new DefaultValueResolver(), | ||
new VariadicValueResolver(), | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Elsewhere, we would also have an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current method of adding them is via a compiler pass, you tag it, gets collected and then injected into the constructor. I'm personally in favour of this method to avoid 4+ method calls each webrequest There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that I'm not in the middle of nowhere with an actual keyboard... This compiler pass does all the logic: https://github.com/symfony/symfony/pull/18308/files#diff-6df4a64da7596af5827901ecbc5d2e78R18
In your service.yml you would only have to do this: services:
app.argument_resolver.user:
class: App\ArgumentResolver\UserValueResolver
arguments:
- "@security.token_storage"
tags:
- { name: controller_argument.value_resolver, priority: 150 } The compiler pass will simply generate an array and replace the second argument to avoid the aforementioned method calls. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I totally understand how that works for Symfony full-stack, I was more thinking about the integration with Silex or Drupal where the FrameworkBundle is not available. Anyway, I'm going to merge like this and we still have 2 months to see how to deal with that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What could be done, is move the compiler pass to the component, but I'm not sure if silex uses this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK Silex does not use Config and DependencyInjection components by default. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once this is merged, let's see if we can find a nice solution for those cases because ideally I'd like to support that before 3.1 is released. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we were to allow to add value resolvers after the argument resolver has been created, we should imo move the priority handling to this class instead of doing that in the compiler pass (i.e. adding a method like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now we have the advantage of little overhead because everything is compiled, I'm personally for this approach because it feels safer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should allow to add value resolver after the argument resolver has been created. 👍 for the current way |
||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\HttpKernel\Tests\ControllerMetadata; | ||
|
||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; | ||
|
||
class ArgumentMetadataTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
public function testDefaultValueAvailable() | ||
{ | ||
$argument = new ArgumentMetadata('foo', 'string', false, true, 'default value'); | ||
|
||
$this->assertTrue($argument->hasDefaultValue()); | ||
$this->assertSame('default value', $argument->getDefaultValue()); | ||
} | ||
|
||
/** | ||
* @expectedException \LogicException | ||
*/ | ||
public function testDefaultValueUnavailable() | ||
{ | ||
$argument = new ArgumentMetadata('foo', 'string', false, false, null); | ||
|
||
$this->assertFalse($argument->hasDefaultValue()); | ||
$argument->getDefaultValue(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller; | ||
|
||
use Symfony\Component\HttpFoundation\Request; | ||
|
||
class ExtendingRequest extends Request | ||
{ | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about merging the last two as being the "fallback" behavior based on reflection? That could even be "hardcoded" (not sure).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean directly in the
ArgumentResolver
or in 1 specific resolver?