When I have an action class with __invoke
method like this:
public function __invoke( ServerRequestInterface $request,ResponseInterface $response,
): ResponseInterface
{
all is working. But when I need to pass arrguments like in case of url /users/{id}
I need to get id argument I make it like this:
public function __invoke( ServerRequestInterface $request,ResponseInterface $response, array $arguments
): ResponseInterface
{
and I’m getting error like
Invoker\Exception\NotEnoughParametersException. Code: 0. Message:Unable to invoke the callable because no value was given for parameter 3 ($arguments). File:vendor/php-di/invoker/src/Invoker.php. Line:78.
My configurations looks like this:
$definitions[Slim\CallableResolverInterface::class] = create(Slim\CallableResolver::class);
$definitions[ResponseFactoryInterface::class] = create(ResponseFactory::class);
$definitions[RouteCollector::class] = create(RouteCollector::class)->constructor(
get(ResponseFactoryInterface::class),
get(CallableResolverInterface::class)
);
$definitions[RouteCollectorInterface::class] = static function(Container $container) {
$config = $container->get(Config::class);
$collector = new RouteCollector(
$container->get(ResponseFactoryInterface::class),
$container->get(CallableResolverInterface::class)
);
if ((bool)$config->get('main.debug') === false && $config->has('main.routes_cache_dir')) {
$collector->setCacheFile((string)$config->get('main.routes_cache_dir') . '/route.cache');
}
return $collector;
};
What I’m doing wrong?
I set up invocation strategy $definitions[InvocationStrategyInterface::class] = create(RequestHandler::class);
But I’m using DI\Bridge\Slim\Bridge
to initialize slim app, and it has scuh a logic:
$container = $container ?: new Container;
$callableResolver = new InvokerCallableResolver($container);
$container->set(CallableResolverInterface::class, new CallableResolver($callableResolver));
$app = AppFactory::createFromContainer($container);
$controllerInvoker = self::createControllerInvoker($container);
$app->getRouteCollector()->setDefaultInvocationStrategy($controllerInvoker);
return $app;
it’s overriding CallableResolverInterface::class
definitions. . Also it’s using controller invoker, so no matter what invoker I set up. Maybe that is the case??
But when I replacing it with a AppFactory::create();
I’m getting error like:
Message: Argument 1 passed to Users\App\Interfaces\MiddleWares\XMLHttpRequestMiddleware::__construct() must implement interface Psr\Http\Message\ResponseFactoryInterface, null given, called in vendor/slim/slim/Slim/CallableResolver.php on line 149
and same with code like this:
AppFactory::setContainer($container);
$app = AppFactory::create();
and even if I passing container instance AppFactory::create(null, $container);
to it’s not solving the issue.
ResponseFactoryInterface
is configured in DI:
$definitions[ResponseFactoryInterface::class] = create(ResponseFactory::class);
So to assume when I’m using DI\Bridge\Slim\Bridge
to initialize app I can’t pass the third argument I’as it by default using controller invoker and you can’t easily replace it with RequestHandler
invoker. When I’m using AppFactory
it’s not working at seems like it’s not injecting DI as it can’t resolve dependencies
I did it. It still should be controller invoker, but for some reason, in the DI\Bridge\Slim\Bridge
it’s probably using wrong invocation strategy, so what I did is:
-
I configure invocation strategy:
$definitions[InvocationStrategyInterface::class] = create(ControllerInvoker::class)->constructor(
new Invoker(new AssociativeArrayResolver())
);
- I replace
DI\Bridge\Slim\Bridge
with own implementation
public static function create(ContainerInterface $container = null): App
{
$container = $container ?: new Container;
$callableResolver = new InvokerCallableResolver($container);
$container->set(CallableResolverInterface::class, new CallableResolver($callableResolver));
$app = AppFactory::createFromContainer($container);
$app->getRouteCollector()->setDefaultInvocationStrategy($container->get(InvocationStrategyInterface::class));
return $app;
}
it’s doing almost the same as DI\Bridge\Slim\Bridge
but it’s using invocation strategy I define, but DI\Bridge\Slim\Bridge
override it with own