Skip to content
This repository has been archived by the owner on Jan 21, 2020. It is now read-only.

PHP 7.1 - typehints, return types, strict types #41

Closed
wants to merge 15 commits into from
Closed

PHP 7.1 - typehints, return types, strict types #41

wants to merge 15 commits into from

Conversation

michalbundyra
Copy link
Member

No description provided.

src/Route.php Outdated
* @throws Exception\InvalidArgumentException for invalid path type.
* @throws Exception\InvalidArgumentException for invalid middleware type.
* @throws Exception\InvalidArgumentException for any invalid HTTP method names.
*/
public function __construct($path, $middleware, $methods = self::HTTP_METHOD_ANY, $name = null)
public function __construct(string $path, $middleware, $methods = self::HTTP_METHOD_ANY, string $name = null)
Copy link
Member Author

Choose a reason for hiding this comment

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

Would be nice if we could typehint on $middleware and $methods.
I've seen somewhere inconsistent with $methods, I think in some place I've seen =null which was translated later on to ANY.

What with $middleware. Is it not now just MiddlewareInterface?

Copy link
Member

Choose a reason for hiding this comment

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

I was just thinking about this myself when I reviewed your earlier patch, and just dove into how zend-expressive uses it.

At this point, within zend-expressive itself, we always pass a middleware instance, as Application::prepareMiddleware() creates an instance based on the argument passed to Application::route(). As such, I think we could likely update this to have a typehint.

We cannot typehint $methods currently, as it can be either an array of HTTP method names or the HTTP_METHOD_ANY constant, which is an integer. I did it this way as the HTTP specification allows arbitrary method names, so there's no way to create a "master list" representing all methods.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated to MiddlewareInterface typehint on $middleware.

About $methods, please see:
https://github.com/zendframework/zend-expressive/pull/530/files#diff-c9248b3167fc44af085b81db2e292837R283
So there we have array $methods = null and then we have:

$methods = null === $methods ? Router\Route::HTTP_METHOD_ANY : $methods;

Maybe we should do the same?
I'm not sure if I like this behaviour (null means any, array defines method explicitly, so emoty array means none).
Similar solution we have on mocking in PHPUnit - setMethods() - we can pass null|array and it has different behaviour with null and empty array.

I would prefer to have it consistent - the same in expressive and expressive-router.

Copy link
Member

Choose a reason for hiding this comment

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

Nullable would work here, I guess; we'd have to change the value of the constant to be null, however, to ensure there's no breakage for folks who use the constant to specify the value. That would allow ?array $methods = null in the signature.

@weierophinney weierophinney added this to the 3.0.0alpha1 milestone Dec 5, 2017
@@ -45,7 +46,7 @@ public function testRouteFailureRetrieveAllHttpMethods()
public function testRouteFailureRetrieveHttpMethods()
{
$result = RouteResult::fromRouteFailure();
$this->assertSame([], $result->getAllowedMethods());
$this->assertSame(['*'], $result->getAllowedMethods());
Copy link
Member Author

Choose a reason for hiding this comment

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

Behaviour here has been changed, we can set default value to [] and typehint on ?array in fromRouteFailure method to keep the previous functionality.
@weierophinney What do you think?

I'd keep it consistent.

Copy link
Member

Choose a reason for hiding this comment

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

We need to make sure that the consumers (the individual routing libraries) are able to upgrade without issue. So long as the same argument types are accepted, how the default works is less important.

That said, [] seems VERY DIFFERENT than ['*']; the first looks like an empty set (no HTTP methods specified), while the latter looks like it accepts a "wildcard" (i.e., any method).

I think in this case, we need to look at the RouteMiddleware in Expressive to determine what it expects.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can't see any usages of fromRouteFailure method in Expressive.

Copy link
Member

Choose a reason for hiding this comment

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

Look in the individual routers, then; just looked, and the FastRouter bridge definitely calls it.

It is changed to keep the previous functionality, defailt value
(mow empty array) will set allowed methods to none
* @throws Exception\RuntimeException when called after match() or
* generateUri() have been called.
*/
public function addRoute(Route $route);
public function addRoute(Route $route) : void;
Copy link
Member

Choose a reason for hiding this comment

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

Ooof. The signature changes in this interface will require new major versions of each router unless we update them to have return values now (return types are covariant, so an implementation can define a more specific return type).

I'll experiment with that momentarily on the zendrouter repo.

* @throws Exception\RuntimeException if unable to generate the given URI.
*/
public function generateUri($name, array $substitutions = [], array $options = []);
public function generateUri(string $name, array $substitutions = [], array $options = []) : string;
Copy link
Member

Choose a reason for hiding this comment

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

And this one requires a major version bump, as the typehint of an argument has changed.

I think we should limit the changes in this interface to return value typehints for now, as it will result in fewer moving parts with regards to coordinating releases.

We can revisit after we have all the various repos updated.

As we allow bind only MiddlewareInterface the method will return
only MiddlewareInterface instances
Copy link
Member

@weierophinney weierophinney left a comment

Choose a reason for hiding this comment

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

Per a conversation on Slack, we agreed that adding the typehints to the interface makes sense, as it solidifies and makes explicit the contract by which implementations must abide. This will, of course, require major-version bumps in each implementation.

.docheader Outdated
@@ -3,3 +3,4 @@
* @copyright Copyright (c) %regexp:(20\d{2}-)?20\d{2}% Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-expressive-router/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
Copy link
Member

Choose a reason for hiding this comment

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

IIRC, we need one empty line between the file-level docblock and any directives, per PSR-12. I'll update those when I merge.

weierophinney added a commit that referenced this pull request Dec 6, 2017
@weierophinney
Copy link
Member

Merged to release-3.0.0 branch; not sure why it didn't auto-close.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants