Slim: getContainer should return a container not an interface

Created on 10 Jul 2018  路  9Comments  路  Source: slimphp/Slim

In my code:

$container = $app->getContainer();
container is an interface

but I need the actuall class that implements that interface.

phpstan complains about it

Most helpful comment

That's why I think it should return a container, which is an implementation of an Interface.

All 9 comments

that is the intended behavior; if you are troubled by the fact that the interface doesn't contain your own methods and properties, you can always annotate they type or check $container instanceof 'YourContainerClass'

maybe extend the default App class, and override the getContainer method

I can't reproduce it, even with the latest version of phpstan v.0.10.1 and level=max

image

Can you give us more details and examples?

        $this->container = $app->getContainer();
        $this->container['errorHandler'] = function ($container)
        {
            return function ($request, $response, $exception) use ($container)
            {
                // not in use
                $request = null;
                $response = null;

                $error = $exception->getMessage();
                $result = $container['view']->fetch('src/Common/views/error.twig', ['error' => $error]);

                return $container['response']->withStatus(500)
                                    ->withHeader('Content-Type', 'text/html')
                                    ->write($result);
            };
        };
       $this->container->get('errorHandler');

line 2 and the last line will cause:
Cannot access offset 'errorHandler' on Psr\Container\ContainerInterface.

Cannot access offset 'errorHandler' on Psr\Container\ContainerInterface.

Ah, a few days ago I got the same error in phpstan. I think this is because the container does not contain the ArrayAccess interface. Strictly speaking, without ArrayAccess you can't access an object like an array. Maybe the Slim Container implemention should implement the ArrayAccess interface too.

$this->container['errorHandler'] = ... // <-- invalid array access on a container interface

ContainerInterface (https://www.php-fig.org/psr/psr-11/) says nothing about ArrayAccess.
As far as I know it's a (handy but custom) implementation of Pimple.
You shouldn't rely on:

$stuff = $container['my_key'];

if you think you might change container.

And this is me thinking out loud: ContainerInterface is a good but incomplete attempt to standardise the containers world. Each one has its own API to register services/dependencies/etc., so the FIG proposal could only cover half the reality of it, which is how to retrieve stuff, which, to me, seems a half-baked solution.

That's why I think it should return a container, which is an implementation of an Interface.

Slim is correct in type hinting the Interface. The question to me is why are you appending a factory after initialisation? You should define everything on startup:

$app = new App([
    'errorHandler' => function(ContainerInterface $c){}
]);

You can replace our container with any other PSR-11 container and Slim will work. Hence we can't type hint getContainer() to return our Container as that's not true - it could be a PHP-DI container for instance.

The only thing we know for sure is that it implements ContainerInterface.

Agree with @akrabat's comment. ContainerInterface is specific for _frameworks_ to have a way to check for classes and then get them. As Slim is a framework, our use is legitimate.

I'm closing this as there is nothing we would do in this specific case. If there is any more info to add, please do and it can be re-opened.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

geggleto picture geggleto  路  4Comments

adambro picture adambro  路  3Comments

snoopy72 picture snoopy72  路  4Comments

jwyuen picture jwyuen  路  5Comments

JamesTheHacker picture JamesTheHacker  路  3Comments