-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[HttpKernel] Bindings scalar named arguments to action method does not work #24555
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
Comments
Hmmm, I know you can specify scalar args if you specify them on the controller.service_arguments tag... so the controller args system does support scalar args. I’m not in a spot to look at the code deeply, but there should be a simple fix: make bind do the same thing that happens with the processing of the args on the tag. Maybe that help... but me (later) or Nicolas may need to check this... |
That's by design: the argument resolver is based on a service locator, and service locators are not compatible with scalar args. Changing this would be considered as a new feature, and would need some discussion because we consciously did not allow so. |
Then we need an appropriate exception message? otherwise it means to me as an incomplete feature.
Agree, that's what I did, but for DX it should be better IMHO, just: -public function postShowAction(Post $post): Response
+public function postShowAction(Post $post, string $env): Response
{
// do something with $env
} vs +private $env;
+public function __constructor(string $env)
+{
+ $this->env = $env;
+}
public function postShowAction(Post $post): Response
{
// do something with $this->env
} mainly if it's used in a single method (which is the case here). |
Ok, we definitely need a clear error :) |
See #24582 |
Actually... this is trickier. We can’t throw an exception, because binding a scalar value is legal in general, and having an argument with the same name as a bound value is also legal. All we can do (I think) is not pass the value to that arg. But, that will be quite unexpected: binding works for the constructor, method calls and most controller args (services, but not scalar). This looks like a wtf to me, and a tough error to spot (why is this arg not being bound). It’s unexpected... and even if it was intentional, it smells like a “bug” (that’s what users will think) |
Absolutely agree with @weaverryan.
👍 |
👍 also |
See #24600 |
… arguments (yceruto) This PR was merged into the 3.4 branch. Discussion ---------- [HttpKernel] Don't bind scalar values to controller method arguments | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | symfony/symfony#24555 (comment) | License | MIT | Doc PR | - See linked issue. Let's suppose we have this configuration: ```yaml services: _defaults: # ... bind: $foo: '%foobar%' ``` `$foo` was successfully bound to any controller constructor, but in another controller I have this edit action (nothing to do with the intention of bind such a parameter, but it has the same name): ```php /** * @route("/{foo}/edit") */ public function editAction(string $foo) {} ``` triggering: > Type error: Argument 1 passed to Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument::__construct() must be an instance of Symfony\Component\DependencyInjection\Reference, string given, called in /home/yceruto/github/symfony/symfony-demo/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php on line 81 or after symfony/symfony#24582: > Invalid service locator definition: only services can be referenced, "string" found for key "foo". Inject parameter values using constructors instead. Commits ------- a1df9af don't bind scalar values to controller method arguments
… arguments (yceruto) This PR was merged into the 3.4 branch. Discussion ---------- [HttpKernel] Don't bind scalar values to controller method arguments | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #24555 (comment) | License | MIT | Doc PR | - See linked issue. Let's suppose we have this configuration: ```yaml services: _defaults: # ... bind: $foo: '%foobar%' ``` `$foo` was successfully bound to any controller constructor, but in another controller I have this edit action (nothing to do with the intention of bind such a parameter, but it has the same name): ```php /** * @route("/{foo}/edit") */ public function editAction(string $foo) {} ``` triggering: > Type error: Argument 1 passed to Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument::__construct() must be an instance of Symfony\Component\DependencyInjection\Reference, string given, called in /home/yceruto/github/symfony/symfony-demo/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php on line 81 or after #24582: > Invalid service locator definition: only services can be referenced, "string" found for key "foo". Inject parameter values using constructors instead. Commits ------- a1df9af don't bind scalar values to controller method arguments
This PR was merged into the 3.3 branch. Discussion ---------- [DI] Enhance service locator error message | Q | A | ------------- | --- | Branch? | 3.3 | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #24555 | License | MIT | Doc PR | - See linked issue. Commits ------- fdb0ea9 [DI] Enhance service locator error message
…ers (weaverryan) This PR was merged into the 3.3 branch. Discussion ---------- Adding warning about non-service arguments for controllers Hi guys! See: symfony/symfony#24555 (comment) This is for 3.3. In 3.4 we can improve this further: by updating the example of this to use `bind` (which is much nicer than the ugly tag) and probably show an example of using `bind` along with a scalar argument to the constructor. In other words, 3.4 is a todo once this is merged. Thanks! Commits ------- 72a0685 Adding warning about non-service arguments
Uh oh!
There was an error while loading. Please reload this page.
I have this controller/action with a scalar argument
$env
:My configuration to bind this argument:
> bin/console cache:clear
:Setting a plain string value (
$args[$p->name] = $bindingValue;
->'%kernel.environment%'
)...symfony/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php
Lines 137 to 139 in 42390a2
...that later will be passed to
ServiceLocatorTagPass::register()
which expects aReference
instance for each arg:symfony/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php
Lines 160 to 162 in 42390a2
I don't have idea how it should be solved, so repo/branch to reproduce the bug:
Note: This work fine with constructor arguments (as
__constructor
method is not included in the previous "pass" butResolveBindingsPass
).ping @nicolas-grekas, @GuilhemN
The text was updated successfully, but these errors were encountered: