This repository was archived by the owner on Jan 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 91
Updated AbstractActionController::indexAction return type to reflect real usage #312
Open
Slamdunk
wants to merge
2
commits into
zendframework:master
Choose a base branch
from
Slamdunk:index_action_return_type
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 we want to support every handled type it should be:
null|void|array|ModelInterface|ResponseInterface
addingvoid
and using theModelInterface
.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.
ModelInterface
, I was deceived by the alias in DefaultRenderingStrategyvoid
? In the years I use ZF 2/3, I've always returned something in the actions, if needed the users shall use explicitreturn null;
statementsThere 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.
as the same if I say:
array
, if need the users shall use explicitreturn new ViewModel()
null
, if need the users shall use explicitreturn new ViewModel()
This is related to my comment in the discussion.
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 understand: I would like to be a bit more pragmatic with this PR
return;
toreturn null;
is ok IMHO, this specific type awareness is important and easy to implement, and the occurrences would be very few as far as I can tellnull|array
toViewModel
the indexAction would for sure mean updating all the codebases that use zend-mvc, a bit harsh move, wouldn't it?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.
Honestly, eventually we should have it be just
void
.PSR-14 (event dispatcher) ignores return values from listeners. As such, if/when we adopt it, we will need controllers to update the event instead of returning a value.
For now,
mixed
is probably the best possible solution for a return type hint, as you can return basically anything; some things are just more of interest to the event dispatcher than others currently.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.
Also, what return type is allowed is defined by the listeners. By default they allow null, array, view model and response.
mixed
should be on the list, technically, but in practice i never seen anything else returned from controllers.Implementers can declare overriding return type if they intentionally return anything else. phpstan and co won't complain about that, will they?
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.
@Xerkus I'm well aware of how actions work! My point is that it would likely make far more sense for actions to have
void
returns, and be passed the event (and, potentially, the request and/or response instance), and call methods on it, instead of returning a value.Right now, what happens is this:
onDispatch()
takes the return value, passes it toMvcEvent::setResult()
, and returns it.DispatchListener
checks to see if the return value is an associative array, and, if so, casts it to anArrayObject
and pushes it back into theMvcEvent::setResult()
method, and returns the value.Application::run()
checks to see if the last result returned is a response; if so, it returns it, but otherwise it ignores the return value.The only reason for pushing a return value other than a response to
MvcEvent::setResult()
is to allow later listeners on the event to act on the results of previous listeners. Currently, this occurs with one of the following:associative array/ArrayObject instances and null return values trigger the
CreateViewModelListener
, which will cast the value to aViewModel
instance and pass it back toMvcEvent::setResult()
.ViewModel
instances trigger theInjectViewModelListener
to inject the result into the existing view model composed in the event, and theInjectTemplateListener
to push a template name into the view model if none was specified.As such, for the shipped functionality, we'd have:
void|null|array|ViewModel|Response
. Whyvoid
? Because a controller might operate on the event or its children directly, without returning a Response to indicate processing is complete. Forcing areturn null
does not mimic real-world usage; furthermore, anull
return forces injection of an emptyViewModel
, which may or may not be desired.In terms of what is allowed,
MvcEvent::setResult()
allowsmixed
, which allows later listeners to act on whatever value is present, regardless of type. If we want to be explicit about whatIndexAction
can return and what the default shipped functionality will work with, it should includemixed
, and, in its entirety readvoid|null|array|ViewModel|Response|mixed
.Tangent time.
Since the only return value that is of interest to the MVC workflow is a response, it would make far more sense for controllers to not return a value unless it is a response at this time. Even better: have a new method on the
MvcEvent
,finalizeResponse(ResponseInterface $response)
, which would stop propagation;Application::run()
would check for a finalized response and return it.If a controller wants to set a view model in the event, do it explicitly. Listeners can check to see if view models have templates set, and, if not, set them. Listeners can also set default view models if none are present. If the controller wants to update the response, but not mark it as final, it can do just that (by omitting a call to
finalizeResponse()
).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.
@Xerkus overriding return types is always preferred and boosted, and static analyzer won't complain, instead will thank for more accurate documentation about typing.
This entirely PR, as written, solely targets
indexAction
s without any return type documented, neither native nor docblock ones, which I assume are a lot, since static analyzers came out after ZF spreaded.@weierophinney this is correct, but I'd point out that in a default zend-mvc installation there are no listener handling anything but
void|null|array|ViewModel|Response
; if a user has custom listener, return types shall be customized and not inheritedAt this point I'm not updating this PR code anymore: feel free to push the changes you consider appropriate 👍
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.
@Slamdunk well, if we do not define mixed in astract but then add bool as a return type in controller implementation we will be violating return type covariance. I can easily see static analysis tools complaining about that
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.
Yes, it would be correct for static analyzers to complain about a bool: no default zend-mvc listener handle booleans as a return type from controller actions