-
-
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
RequestResponseNamedArgs and Typed Parameters #3198
Comments
By default, Slim controllers have a strict signature: But generally, this is also quite easy to write it like this (without RequestResponseNamedArgs): $app->get('/test/{id}', function($request, $response, array $args) {
$id = (int)$args['id'];
// ...
}); |
@odan The |
That's right, obviously this feature was added in version 4.1. #3132 I guess this specific feature (typed parameters) is not supported at the moment, because the ... operator in combination with
|
@odan Like I mentioned in the original issue, the type strictness of a call is determined by the calling file, not the called file, so removing strictness on my controller classes wouldn't affect anything. |
This will be fixed in Slim 5. In Slim 4 you try to add the following strategy: Installation:
Add this custom strategy class: File: <?php
declare(strict_types=1);
namespace App\Strategies;
use Invoker\InvokerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Interfaces\InvocationStrategyInterface;
final class RequestResponseTypedArgs implements InvocationStrategyInterface
{
private InvokerInterface $invoker;
public function __construct(InvokerInterface $invoker)
{
$this->invoker = $invoker;
}
public function __invoke(
callable $callable,
ServerRequestInterface $request,
ResponseInterface $response,
array $routeArguments
): ResponseInterface {
$routeArguments['request'] ??= $request;
$routeArguments['response'] ??= $response;
return $this->invoker->call($callable, $routeArguments);
}
} Set as default invocation strategy: use App\Strategies\RequestResponseTypedArgs;
use Invoker\Invoker;
// ...
$container = $app->getContainer();
$strategy = new RequestResponseTypedArgs(new Invoker(null, $container));
$routeCollector = $app->getRouteCollector();
$routeCollector->setDefaultInvocationStrategy($strategy);
// ... |
I was in the process of migrating my web application to use the Slim
RequestResponseNamedArgs
controller invoker in favor of the previous PHP-DI/Invoker-based one I was using, and I had expected that the transition would be a fairly straightforward one, but I'm running into one big issue: if you type a parameter in a controller action, for example as anint
, it can never coerce into that value:The reason this fails is because, at least per my own research, there's no way to specify that a route parameter should be cast as an integer, even if it only accepts numeric values per its FastRoute config. Because
declare(strict_types=1)
is set on theRequestResponseNamedArgs
class, it won't coerce the always-string values for parameters to fit the typed argument in the action.I'm not sure what the elegant solution to this is. You could remove the strict typing from that single class, since any type strictness originates from the calling file and this would allow type coercion...or somehow let FastRoute know that it should be parsing some parameters as integers.
I'm not even sure that it's something you'd want to fix on the framework side at all, instead choosing to say that every passed parameter will be a string because, well, URLs are strings. That's certainly what my immediate resolution will be, just to re-type all of those action arguments as strings and parse them down the line.
The text was updated successfully, but these errors were encountered: