Yii2: DI as component of application?

Created on 27 Oct 2017  路  12Comments  路  Source: yiisoft/yii2

So... I can see $container is a public static property of BaseYii class.

How about add it to di component of module? This make since?

(I can see something similar in @SamMousa issue)

...
    'components' => [
        'di' => function() {
            return Yii::$container;
        },
...

Will be get from controller in module

        $container = Yii::$app->get('di'); // Dependency Injection Container
        // or
        $container = $this->module->get('di'); // Dependency Injection Container
        $model = $container->get($this->modelNameOfContactForm); //do someting

let's discuss!

Additional info

| Q | A
| ---------------- | ---
| Yii version | 2.0.13 dev

under discussion

Most helpful comment

I don't think the container should be a component; but I do think the container should be application / module specific. And not a global static.

It means less global state outside the application object.

All 12 comments

What's the benefit for doing so?

Any (some) examples in guide don't show how to $container will be create.

This is propose idea of multiple container's... For modules...

I don't think the container should be a component; but I do think the container should be application / module specific. And not a global static.

It means less global state outside the application object.

Container can not be an application component, application should be a part of container instead.

Agreed with @SamMousa. I was thinking about replacing ServiceLocator (SL) with Container (interface is pretty much the same) and making it module-specific (as SL is now) so we can always call $this->module->get() instead of calling global objects.

In order to properly do that we should add support for container inheritance.

Container inheritance is a much discussed subject; angular 2 does it. I think it was discussed for psr container spec as well...

@silverfire application config might be in container but IMO a container instance should be in the application...

Container can not be an application component, application should be a part of container instead.

Cycle link? Application is a part of container; container is a application component (get from function)

I do think the container should be application / module specific. And not a global static.
It means less global state outside the application object.

...
    'components' => [
        'di' => function() {
            return Yii::$container;
        },
    ],
    'modules' => [
        'v1' => [
            'class' => \api\v1\Module::class,
            'components' => [
                'di' => function() {
                    return \api\v1\Module::$container; //or some else
                },
            ],
        ],
        'v2' => [
            'class' => \api\v2\Module::class,
            'components' => [
                'di' => function() {
                    return \api\v2\Module::$container; //or some else non-static
                },
            ],
        ],
    ],
...

Will be get from controller in module

        $container = Yii::$app->get('di'); // Dependency Injection Container
        $model = $container->get($this->modelNameOfContactForm); //do someting in app di
        // or
        $container = $this->module->get('di'); // Dependency Injection Container
        $model = $container->get($this->modelNameOfContactForm); //do someting in module di

this is will work?

No, now it is still static Yii::$container, you just have an extra reference.

If the DI container creates the application object it must be created before the application. It could of course inject itself into the application.

````
class Application {
public function __construct(Container $container)
{

}

// Create container:
$container = new Container(['app' => ['class' => Application::class, ...]]);
// Run application via invoke.
$container->invoke(function(Application $app) {
$app->run();
});
// Run application via get:
$container->get(Application::class)->run();

````

Of course the container injected into the application does not have to be the same container. In fact, there is no reason to make the container a singleton; instead it would make sense to create a copy for "each" application instance, that way you only need to use the initial DI container to instantiate the application(s).
And at that point, if you create a DI container to instantiate one object, you're not doing DI, you're not even really doing SL, you're just doing a new in a weird way.
Of course suppose your creating a ReactPHP type web server that uses multiple application objects to handle requests using DI for application creation makes sense...

@SamMousa how about still alive \Yii::$container AND add more di container in bootstrap/config modules for work with module-dependence relations? This make sense for cross-modules communication, module-depend relations or any else like this?

It doesn't remove the global; which is the most important thing imo.

Decided not to change DI container much in 3.0. See roadmap.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

schmunk42 picture schmunk42  路  47Comments

rosancoderian picture rosancoderian  路  46Comments

alexandernst picture alexandernst  路  163Comments

AstRonin picture AstRonin  路  49Comments

Faryshta picture Faryshta  路  48Comments