-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Add new RequestResponseNamedArgs
route strategy
#3132
Add new RequestResponseNamedArgs
route strategy
#3132
Conversation
I like this strategy, it sucks that named parameter mapping isn't available in 7.4 though. @akrabat what do you think of adding this? It's only available for PHP 8.0 which makes me reluctant. Maybe this should be a Slim 5 feature instead. |
I fixed the CS issue in the test file. Sorry about that. Also, I agree that it sucks that this is only available for 8.0+ but 7.4 is now in security fixes only. |
We could make the basic use case work with some reflection like this : public function __invoke(
callable $callable,
ServerRequestInterface $request,
ResponseInterface $response,
array $routeArguments
): ResponseInterface {
if (PHP_VERSION_ID >= 80000) {
return $callable($request, $response, ...$routeArguments);
}
$args = [ $request, $response ];
$rf = new ReflectionFunction($callable);
$parameters = $rf->getParameters();
$parametersCount = count($parameters);
$hasVariadic = false;
for ($i = 2; $i < $parametersCount; $i++) {
if ($parameters[$i]->isVariadic()) {
$hasVariadic = true;
$args = array_merge($args, array_values($routeArguments));
} else {
$parameterName = $parameters[$i]->getName();
if (isset($routeArguments[$parameterName])) {
$args[] = $routeArguments[$parameterName];
unset($routeArguments[$parameterName]);
} elseif ($parameters[$i]->isOptional()) {
$args[] = $parameters[$i]->getDefaultValue();
} else {
throw new \Exception(sprintf('Argument #%d ($%s) not passed', $i, $parameterName));
}
}
}
if (!$hasVariadic && !empty($routeArguments)) {
$parameterName = key($routeArguments);
throw new \Exception(sprintf('Unknown named parameter $%s', $parameterName));
}
return $callable(...$args);
} If you like this (I'm not a fan of it) we would have to discuss :
I don't think it's worth it for a version that will not be supported in less than a year. But I'm just giving the different solutions so that you can take the one that feet the best with your vision. |
I agree with this wholeheartedly actually. I'm fine with merging this after some thought. Can we write a test for the constructor exception please? |
Thanks. I added some tests for both 8.0+ and 7.4 but the coverage will still decrease since the coverage run on 8.1. |
@adoy you should be able to override |
Just to make sure to understand, isn't it enough to have one test for PHP7.4 to make sure the exception is thrown and other for PHP8.X to make sure the behaviour is correct ? If I create an Helper function, we'll have the same problem to test this function, if I use the constant inside this helper function. Is it only to have the 100% coverage under PHP8.1 ? As for the constant it is a PHP defined constant so I can not overwrite it, and if I create it only in the used namespace, I will only have the oportunity to define it once, so for only one use case. Thanks for your insight, it will help me find the best way to resolve 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.
Just one little thing then I'll merge this.
I noticed that the coverage went down because the exception thrown test is not being run since we run code coverage on php 8. It's fine though.
Thanks
public function __construct() | ||
{ | ||
if (PHP_VERSION_ID < 80000) { | ||
throw new \RuntimeException('Named arguments are only available for PHP >= 8.0.0'); |
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.
Can we add the use RuntimeException;
statement on line 16 and remove the \
here please
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.
Sure !
PHP8.0 added support for named parameters https://wiki.php.net/rfc/named_params This new strategy will map route to parameters name. ``` $app->get('/{greeting}/{name}', function (ServerRequestInterface $request, ResponseInterface $response, $name, $greeting) { $response->getBody()->write("{$greeting} {$name}"); return $response; }); ```
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.
Thank you for this contribution!
PHP8.0 added support for named parameters https://wiki.php.net/rfc/named_params
This new strategy will map route to parameters name.