Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[HttpKernel] Fix ArgumentValueResolver for arguments default null#21333

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

@chalasr
Copy link
Member

@chalasrchalasr commentedJan 18, 2017
edited
Loading

QA
Branch?2.7
Bug fix?yes
New feature?no
BC breaks?no
Deprecations?no
Tests pass?yes
Fixed ticketsn/a
LicenseMIT
Doc PRn/a

If an argument hasnull as default valueand annotations are used for routing, then it is not resolved by the ArgumentResolver e.g:

publicfunctionshowAction(Request$request) {dump($request);// Request object}publicfunctionshowAction(?Request$request) {dump($request);// Request object}publicfunctionshowAction(Request$request =null) {dump($request);// null}

To me, the last example should have been a Request object too.

Note that it is the same behavior when usingUserInterface or whatever, I ran into this issue while trying to dump a user for a route accepting both anonymous and authenticated requests, the argument was always null while$this->getUser() returned the expected value. According tohttp://symfony.com/blog/new-in-symfony-3-2-user-value-resolver-for-controllers it should have worked through the argument.

I propose to make it works as a bugfix.
Any suggestion for improving the patch will be really welcomed. ping@iltar

@chalasr
Copy link
MemberAuthor

chalasr commentedJan 18, 2017
edited
Loading

There is no BC break nor deprecation here, please remove the corresponding labels, my bad sorry.

@chalasrchalasrforce-pushed thekernel/resolve-nullable-arguments branch 2 times, most recently from50b4bc7 tod49390dCompareJanuary 18, 2017 13:32

foreach ($reflection->getParameters()as$param) {
$arguments[] =newArgumentMetadata($param->getName(),$this->getType($param),$this->isVariadic($param),$this->hasDefaultValue($param),$this->getDefaultValue($param),$param->allowsNull());
$arguments[] =newArgumentMetadata($param->getName(),$this->getType($param),$this->isVariadic($param),$this->hasDefaultValue($param),$this->getDefaultValue($param),$this->isDefaultNull($param));
Copy link
MemberAuthor

@chalasrchalasrJan 18, 2017
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

ReflectionParameter::allowsNull() returns true for mandatory arguments which don't have any type hint i.e:function ($foo); // allowsNull(): true
Here we only want to know if the argument is default null, or has a typehint which allows null i.e.?type

@linaori
Copy link
Contributor

How come it injectsnull instead of theRequest? In theory the Request resolver should inject it as the default value one is triggered way later

@chalasr
Copy link
MemberAuthor

chalasr commentedJan 18, 2017
edited
Loading

Not sure but I believe the current implementation makes the Request resolver is just skipped so the default value wins. It can be reproduced with a fresh SE, changing the providedDefaultController::indexAction(Request $request) toDefaultController::indexAction(Request $request = null);

@linaori
Copy link
Contributor

But that would mean that this code is not hit properly:https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestValueResolver.php#L30-L38

Can you confirm this? Because this code is responsible for setting the request if it's supported and should work with the original setup (in theory).

@chalasr
Copy link
MemberAuthor

chalasr commentedJan 18, 2017
edited
Loading

@iltar I can confirm this since usingindexAction(Request $request = null) and adding adump($request);die; immediately before this linehttps://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestValueResolver.php#L30, the dump is never reached.

But right now I'm not able to say what exactly is wrong with the current implem, the patch made here avoids the only doubts I have about the origin of the issue (one beingcontinue 2;) while covering all other cases that are working well originally, I was hoping you can say me more :/

@chalasrchalasrforce-pushed thekernel/resolve-nullable-arguments branch from0473c18 to46758c7CompareJanuary 18, 2017 17:30
@linaori
Copy link
Contributor

I'll try to reproduce it tomorrow. Maybe it's a sequence issue, because in theory this is only not called when something else already supports it and thecontinue 2; is hit. So if something else hits this first, there is probably another issue at hand.

@chalasrchalasrforce-pushed thekernel/resolve-nullable-arguments branch from46758c7 to86931d5CompareJanuary 18, 2017 19:37
@chalasr
Copy link
MemberAuthor

chalasr commentedJan 18, 2017
edited
Loading

Maybe it's a sequence issue

Right! I looked deeper into and fact is that the RequestAttributeValueResolver is the culprit.
I updated this PR to give it a lower priority than theRequestValueResolver/SecurityUserValueResolver, but maybe there's something wrong in the request argument one that should be fixed instead.
Waiting for your feedback.

@chalasrchalasr changed the title[HttpKernel] Fix ArgumentResolver for argument with default null[HttpKernel] Fix ArgumentValueResolver registration orderJan 18, 2017
@linaori
Copy link
Contributor

linaori commentedJan 18, 2017
edited
Loading

@chalasr is there a specific reason that this line is returning true?https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php#L30

Perhaps the'request' key is created for some reason? Not sure why a null'request' key would return true in a has here. Regarding your fix, if having the request in the attribute bag but as null is correct (which I kinda doubt), make sure the request attribute resolver is still called before theRequestValueResolver, due to the parameter converters

@chalasr
Copy link
MemberAuthor

chalasr commentedJan 18, 2017
edited
Loading

make sure the request attribute resolver is still called before the RequestValueResolver, due to the parameter converters

Did not considered that :/ then the current fix is not good, it just gives a lower priority to the request attribute resolver so it is called after the request/user resolver.

Perhaps the "request" key is created for some reason?

Right again! Arequest (variable name) key is put in the attribute bag withnull as value. Same problem for theSecurityUserValueResolver given auser attribute withnull as value exists, theRequestAttributeValueResolver takes precedence of course...

Not sure what's the proper way to fix this :/ Any idea@iltar?

@linaori
Copy link
Contributor

I think we have to check why the attributes are created but empty, perhaps this is done for the parameter converters? An additional check could be to check if ithas() the key and it's not empty

@chalasr
Copy link
MemberAuthor

chalasr commentedJan 18, 2017
edited
Loading

perhaps this is done for the parameter converters?

Not sure but there're good chances. Note that these attributes stay null at the end (from the controller itself) since I do not have any param converter explicitly configured

make sure the request attribute resolver is still called before the RequestValueResolver, due to the parameter converters

Could you please develop?
How calling the request/user resolvers before the request attribute one would be a problem for param converters? I mean if one sets up an argument value resolver for a given argument, then he should not rely on a param converter to populate it, should he?

An additional check could be to check if it has() the key and it's not empty

If you mean adding an additional check insideRequestAttributeValueResolver::supports() I think it could help indeed, I'd say a strictnull !== $attribute though

@linaori
Copy link
Contributor

linaori commentedJan 18, 2017
edited
Loading

ThePC attribute resolver should be called first because that's how the behavior was before the argument value resolvers were introduced. if attributes.foo existed, 'foo' should be inserted first rather than trigger the PCs (when passing in templates for example).

edit: Not PC but attribute resolver should be called first

@chalasrchalasrforce-pushed thekernel/resolve-nullable-arguments branch from86931d5 to426fafcCompareJanuary 18, 2017 20:32
@chalasr
Copy link
MemberAuthor

chalasr commentedJan 18, 2017
edited
Loading

I updated this for reverting the previous changes and only adding the additionalnull !== $attribute check instead, it fixes the issue.
It would be great if you could have a look at it and confirm it won't cause any issue with PCs.

@chalasrchalasr changed the title[HttpKernel] Fix ArgumentValueResolver registration order[HttpKernel] Fix ArgumentValueResolver for arguments default nullJan 18, 2017

$argumentName =$argument->getName();

return$request->attributes->has($argumentName) &&null !==$request->attributes->get($argumentName);
Copy link
Contributor

@linaorilinaoriJan 18, 2017
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Hmm I'm curious what happens if you have this:

$request->attributes->set('required', null);public function fooAction(string $required);

edit: probably already broken/proper error in an old version?

Copy link
MemberAuthor

@chalasrchalasrJan 18, 2017
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Using:

/** * @Route("/", name="homepage", defaults={"required": null}) */publicfunctionindexAction(string$required){}

Controller "AppBundle\Controller\DefaultController::indexAction()" requires that you provide a value for the "$required" argument [...]

Changing the signature toindexAction(string $required = null); orindexAction(?string $required); works of course.

Same behavior on 3.0, run into the same exception if the attribute is null.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

But this will now break the case where an attribute was set tonull deliberately. Isn't that a BC break?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Indeed, it is...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

With this signature it would fail already, you just simply can't set it tonull anymore and it will trigger the resolver.

// call this with null, it will still trigger the resolverpublicfunction fooAction(UserInterface$user =null);

But I'm still curious as of why the request values are null in the attribute bag.

@xabbuh regarding the above example, that would fail already. Also I don't think that values not mapped in the route should be affecting the parameter resolvers:

  • /{required} with(string $required) = allowed to be set to null but will throw an error as its required
  • / with(string $required) != allowed to set to null, as it was not added in the route definition

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@iltar it happens only when the argument has a default, I'll look if avoiding this breaks something but I think you're right. If we can remove this magic then the resolver stays as it is and continue to work as expected in case the attribute is set explicitly

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

If you ask me, routing information should not be affected by arguments in the method that are not mapped in the route, but that's exactly what happens right now 😢

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@iltar No, I mean a parameter without a type hint and without a default value.

Copy link
MemberAuthor

@chalasrchalasrJan 19, 2017
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@xabbuh it could even break for ones that are type-hinted as objects with null as default value I think, which is what we are trying to fix. The current approach is definitely not the good one.

routing information should not be affected by arguments in the method that are not mapped in the route

I agree, but I don't know if it is expected somewhere internally (if someone has an hint?), nor where it happens

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@xabbuh I agree on that point. If the compiled route would be without the default value, everything will work as expected

@chalasr
Copy link
MemberAuthor

@iltar My bad, I forgot to revert it. The diff is clean now

@chalasrchalasrforce-pushed thekernel/resolve-nullable-arguments branch fromc9f527f toe31ad5aCompareJanuary 19, 2017 09:55
@linaori
Copy link
Contributor

Nice! 👍

So just for the confirmation, this behavior is only present with annotations?

@chalasr
Copy link
MemberAuthor

Yes, it is only present for annotations, which make this bug exists only when using them.

linaori reacted with hooray emoji

Copy link
Contributor

@linaorilinaori left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Seems like a double fix to me

@chalasrchalasrforce-pushed thekernel/resolve-nullable-arguments branch frome31ad5a to2c808caCompareJanuary 19, 2017 14:41
@fabpot
Copy link
Member

fabpot commentedJan 19, 2017
edited
Loading

The code you removed was introduced in84adcb1 by@lyrixx. See#5904 for the associated PR.

@chalasr
Copy link
MemberAuthor

chalasr commentedJan 19, 2017
edited
Loading

@fabpot I found it and was about to add a comment for clarifying this patch after discussed it with@iltar and@xabbuh on slack.

The code removed here seems unnecessary, arguments with default values properly keep their default value even after removing it, same on 3.0.
Actually, it seems that this code sets attributes that are not needed, and it prevents the ArgumentResolver from resolving these arguments (since they have an equivalent request attribute which takes precedence), and this only occurs when using annotations.

@lyrixx Could you please confirm that this code is no more needed and that removing it in 2.7 would not break anything? The bug fixed here exists on 2.7 as well, before that argument value resolvers were introduced.

@fabpot
Copy link
Member

If the tests added back then by@lyrixx still work after the removal, I would say that this is safe to do on 2.7 instead of 3.1. Any drawbacks?

@chalasrchalasr changed the base branch from3.1 to2.7January 19, 2017 16:02
@chalasrchalasrforce-pushed thekernel/resolve-nullable-arguments branch from2c808ca tof014cb6CompareJanuary 19, 2017 16:02
@chalasrchalasrforce-pushed thekernel/resolve-nullable-arguments branch fromf014cb6 tod3fa8a1CompareJanuary 19, 2017 16:03
@chalasr
Copy link
MemberAuthor

Changed the target to 2.7. Tests seem green, let's see the build.

@lyrixx
Copy link
Member

Could you please confirm that this code is no more needed and that removing it in 2.7 would not break anything? The bug fixed here exists on 2.7 as well, before that argument value resolvers were introduced.

Actually I don't know. The best way to know it is to test in a real project I guess.

@chalasr
Copy link
MemberAuthor

Ok thanks, tried out on 2.7 and it works as expected (for the record:screenshot on a fresh 2.7).

@fabpot
Copy link
Member

Thank you@chalasr.

@fabpotfabpot merged commitd3fa8a1 intosymfony:2.7Jan 19, 2017
fabpot added a commit that referenced this pull requestJan 19, 2017
…lt null (chalasr)This PR was merged into the 2.7 branch.Discussion----------[HttpKernel] Fix ArgumentValueResolver for arguments default null| Q             | A| ------------- | ---| Branch?       | 2.7| Bug fix?      | yes| New feature?  | no| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets | n/a| License       | MIT| Doc PR        | n/aIf an argument has `null` as default value __and annotations are used for routing__, then it is not resolved by the ArgumentResolver e.g:```phppublic function showAction(Request $request) {   dump($request); // Request object}public function showAction(?Request $request) {   dump($request); // Request object}public function showAction(Request $request = null) {   dump($request); // null}```To me, the last example should have been a Request object too.Note that it is the same behavior when using `UserInterface` or whatever, I ran into this issue while trying to dump a user for a route accepting both anonymous and authenticated requests, the argument was always null while `$this->getUser()` returned the expected value. According tohttp://symfony.com/blog/new-in-symfony-3-2-user-value-resolver-for-controllers it should have worked through the argument.I propose to make it works as a bugfix.Any suggestion for improving the patch will be really welcomed. ping@iltarCommits-------d3fa8a1 Avoid setting request attributes from signature arguments in AnnotationClassLoader
@chalasrchalasr deleted the kernel/resolve-nullable-arguments branchJanuary 19, 2017 17:09
fabpot added a commit that referenced this pull requestJan 24, 2017
… attributes handling (chalasr)This PR was merged into the 2.7 branch.Discussion----------[Routing] Fix BC break in AnnotationClassLoader defaults attributes handling| Q             | A| ------------- | ---| Branch?       | 2.7| Bug fix?      | no| New feature?  | no| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets |77289b9#commitcomment-20572462| License       | MIT| Doc PR        | n/aThis fixes a BC break introduced in#21333. Instead of removing the automatic request attributes creation, we keep it but only for attributes that are mandatory (i.e. present in the route path).Thanks to@iltar for the idea.Commits-------1d298f0 [Routing] Fix BC break in AnnotationClassLoader defaults attributes handling
@fabpotfabpot mentioned this pull requestJan 28, 2017
This was referencedFeb 6, 2017
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@xabbuhxabbuhxabbuh left review comments

+1 more reviewer

@linaorilinaorilinaori approved these changes

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

6 participants

@chalasr@linaori@fabpot@lyrixx@xabbuh@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp