-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[HttpKernel] Added the SessionValueResolver #21164
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
Conversation
@@ -0,0 +1,9 @@ | |||
<?php | |||
|
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.
Small somewhat unrelated sidenote, I noticed only the NullableController.php
has a copyright docblock but the others do not... Most of the fixture files have them, should it also be added?
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.
For consistency, I can add them yes
*/ | ||
public function resolve(Request $request, ArgumentMetadata $argument) | ||
{ | ||
yield $request->getSession(); |
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.
The test above does not ensure that the returned value will be a Session
instance, only the argument type is checked, this could return any implementation of the interface (https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L741), so you should add a test for it I guess.
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 should add a test for it I guess.
I meant a unit test.
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.
Added, see testGetSessionArgumentsWithInterface
*/ | ||
public function supports(Request $request, ArgumentMetadata $argument) | ||
{ | ||
return (Session::class === $argument->getType() || is_subclass_of($argument->getType(), Session::class)) && $request->hasSession(); |
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.
I suggest:
if (Session::class !== $argument->getType() || !is_subclass_of($argument->getType(), Session::class)) {
return false;
}
return $request->getSession() instanceof Session;
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.
Good catch, that's what I get for staying up late and rushing it ;)
I think fabbot.io is giving false positives, I haven't touched those lines and I think they are correct the way they are /cc @fabpot |
Indeed, can you try to rebase to see if that fixes the issue? |
|
Opps, I thought that PHP-CS-Fixer/PHP-CS-Fixer#2421 was already merged but I was wrong :( |
*/ | ||
public function supports(Request $request, ArgumentMetadata $argument) | ||
{ | ||
if (Session::class !== $argument->getType() && !is_subclass_of($argument->getType(), Session::class)) { |
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.
Shouldn't we check on SessionInterface to allow type-hinting with the interface when we only need methods that are in the interface ?
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.
I explicitly mentioned Session
over SessionInterface
here due to statefulness, which is implementation specific. I could change it to the interface of course.
What do you guys think of this?
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.
I think we should support both as we also maintain both. The Session
type hint would be useful if you really need the flash bag, for example. Using the SessionInterface
is great for interoperability especially in third-party bundles.
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
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.
These changes should probably better be introduced on older branches.
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.
I'll put them on 3.1 in that case
For now I'm 👎 about this proposal. My reasons:
|
Except that I don't extend the base controller, so this is of no use for me. Everyone using Controller as a Service will run into this problem.
It's not about optimization, but about type-hints (see #21159, it lists all issues related).
If you ask me:
The session can be different each time it's called, therefore it shouldn't be a constructor dependency. However, when using the
Doctrine/The EM is a stateless dependency and not an object with contextual value. |
This PR was merged into the 3.1 branch. Discussion ---------- Added missing headers in fixture files | Q | A | ------------- | --- | Branch? | 3.1 | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | n/a | Fixed tickets | ~ | License | MIT | Doc PR | ~ The headers were missing in a few files as mentioned in #21164 (comment) Commits ------- c9c2474 Added missing headers in fixture files
return false; | ||
} | ||
|
||
return $request->hasSession(); |
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.
Maybe we should check that the session is of the type-hinted class ($request->getSession() instanceof $argument->getType()
)?
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.
The return type of getSession()
is SessionInterface
. The AVR supports everything extending the SessionInterface
, thus merely checking if it has as session, is enough imo
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.
But if someone type hint with Session
and that $request->getSession()
doesn't return a Session
but another class implementing SessionInterface
we will get a type error instead of the "no argument value resolver" error.
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.
Right! I'll add a test case
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.
@jvasseur should be fixed now
I like this proposal. It's a step toward #10557 |
*/ | ||
public function supports(Request $request, ArgumentMetadata $argument) | ||
{ | ||
if (SessionInterface::class !== $argument->getType() && !is_subclass_of($argument->getType(), SessionInterface::class)) { |
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.
If you want to support both type hints (implementation and interface), what about:
$type = $argument->getType();
if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) {
return false;
}
return $request->getSession() instanceof $type;
?
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.
Hm yeah, I was playing with that idea earlier, but I wasn't sure if instanceof works with that (at least not with a method call), let's see!
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.
Yup, that works a lot cleaner!
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.
👍
Just stumbled across this PR and would like to support it 👍 It currently feels quite wrong to use the session flashbag when using controllers as services instead of extending the base controller (I regard container injection as anti-pattern, even in controllers). |
Rebased against the master, all is green now |
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.
👍
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.
👍
Status: Reviewed
Thank you @iltar. |
This PR was merged into the 3.3-dev branch. Discussion ---------- [HttpKernel] Added the SessionValueResolver | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #21159 | License | MIT | Doc PR | (soon) This feature adds the `SessionValueResolver`. That means that you no longer have to rely on injecting a `SessionInterface` implementation via the constructor or getting this implementation from the `Request`. Regardless of method, it does not know about the `getFlashBag()`. By adding the `Session` to the action arguments, you can now type-hint against the implementation rather than interface, which contains the `getFlashBag()`, making it accessible rather than using duck-typing. _It should also feel less like injecting a service into the constructor which has a state or getting a service from the request._ **Old Situation** ```php class Controller { public function __construct(SessionInterface $session) { /* ... */ } public function fooAction(Request $request) { $this->get('session')->get(...); $request->getSession()->get(...); $this->session->get(...) // duck-typing $this->get('session')->getFlashBag(); $request->getSession()->getFlashBag(); $this->session->getFlashBag(); $this->addFlash(...); } } ``` **New Situation** _- The controller shortcut for flashbag could in theory be removed now_ ```php class Controller { public function fooAction(Session $session) { $session->get(...); $session->getFlashBag(); } } ``` Commits ------- b4464dc Added the SessionValueResolver
This PR was merged into the 3.3-dev branch. Discussion ---------- [HttpKernel] Refactored SessionValueResolver | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | ~ | License | MIT | Doc PR | ~ I thought the comment has been addressed in #21164, but it may have been unintentionally lost while rebasing? Commits ------- f0e832a [HttpKernel] Refactored SessionValueResolver
This PR was squashed before being merged into the master branch (closes #7322). Discussion ---------- Added docs for the SessionValueResolver Explains the functionality added in symfony/symfony#21164 Commits ------- 88b740e Added docs for the SessionValueResolver
This feature adds the
SessionValueResolver
. That means that you no longer have to rely on injecting aSessionInterface
implementation via the constructor or getting this implementation from theRequest
. Regardless of method, it does not know about thegetFlashBag()
.By adding the
Session
to the action arguments, you can now type-hint against the implementation rather than interface, which contains thegetFlashBag()
, making it accessible rather than using duck-typing.It should also feel less like injecting a service into the constructor which has a state or getting a service from the request.
Old Situation
New Situation - The controller shortcut for flashbag could in theory be removed now