Внедрение зависимостей (dependency injection) позволяет получить экземпляр нужного класса из специального объекта «контейнера» с автоматической передачей аргументов его конструктору, вместо того, что бы создавать его самому. Кроме того, контейнер позволяет реализовать шаблон проектирования «Singleton».
В случае фреймворка Yii, данный служебный объект называется «Контейнер внедрения зависимостей». В Laravel – «Сервис-контейнер».

Нужный пользователю объект создается контейнером, при этом все зависимости этого объекта (аргументы) передаются ему автоматически в виде экземпляров указанных классов (или классов реализующих указанные интерфейсы):
public function __construct(EmployeeRepository $employees, EventDispatcher $dispatcher)

Таким образом, вместо (например):
$repository = new YiiEmployeeRepository($db);
$dispatcher = new MailEventDispatcher();

$employeeService = new EmployeeService($repository, $dispatcher);
достаточно прописать:
$employeeService = Yii::$container->get('EmployeeService');

Для того, что бы работало внедрение зависимостей, в контейнере должны быть зарегистрированы и класс, объект которого мы хотим получить, и классы, которые указаны в его конструкторе (зависимости). Таким образом будут созданы и объекты этих классов. Если эти классы так же имеют какие-либо зависимости в своих конструкторах, то и те зависимости должны быть зарегистрированны в контейнере. Все основные классы Yii (например Request или Db) там регистрируются автоматически. Поэтому следить нужно только за пользовательскими.

Если вы создаете объект какого-либо своего класс, например сервиса или репозитория, то их нужно добавить в контейнер, если желаете воспользоваться внедрением зависимостей.


Добаление класса в контейнер внедрения зависимостей.

1. В Yii, это можно сделать прямо добавив секцию container в конфигурационные файлы web.php, console.php и test.php (если работать с yii2-app-basic) или в common/config/main.php (в yii2-app-advanced):
$config = [
    'id' => 'basic',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'container' => [
        'singletons' => [
            'app\repositories\EmployeeRepository' => ['class' => 'app\repositories\YiiEmployeeRepository'],
            'app\dispatchers\EventDispatcher' => ['class' => 'app\dispatchers\MailEventDispatcher'],
            'EmployeeService' => ['class' => 'app\services\EmployeeService'],
        ],
    ],    'components' => [
        ...
    ],
],

Тут регистрируется класс сервиса - 'EmployeeService' и две его зависимости из примера выше. Для самого сервиса указываю его короткое название – алиас, чтобы получать его из контейнера по данному алиасу.

Вместо свойства singletons можно было бы указать свойство definitions. singletons указывается, если мы хотим работать всегда только с одним экземпляром указанных классов, а не создавать, каждый раз, новый объект. Каждый раз, когда у контейнера вызывается метод get(), возвращается тот же экземпляр указанного класса.



2. Кроме указания в конфигурационных файлах Yii, добавить классы в контейнер можно с помощью его методов, в данном случае setSingleton(). Делать это, желательно, на этапе загрузки приложения, а не где-то в контроллере. Для этого как раз предназначен класс Bootstrap. Моя статья про предзагрузку в Yii http://klisl.com/yii2-bootstrap.html

Создаем класс Bootstrap (если нету), реализующий интерфейс BootstrapInterface и регистрируем в нем классы:
<?php

namespace app;

use app\dispatchers\EventDispatcher;
use app\dispatchers\MailEventDispatcher;
use app\repositories\EmployeeRepository;
use app\repositories\YiiEmployeeRepository;
use app\services\EmployeeService;
use yii\base\BootstrapInterface;


class Bootstrap implements BootstrapInterface
{
    public function bootstrap($app)
    {
        $container = \Yii::$container;
        $container->setSingleton(EventDispatcher::class, MailEventDispatcher::class);
        $container->setSingleton(EmployeeRepository::class, YiiEmployeeRepository::class);
        $container->setSingleton('EmployeeService', EmployeeService::class);
    }
}


Если не нужно использовать шаблон проектирования Singleton, регистрируем таким образом:
$container->setDefinitions([
    EventDispatcher::class => MailEventDispatcher::class
]);

Класс Bootstrap так же нужно зарегистрировать, чтобы он загрузился при запуске приложения. Для этого в конфигурационном файле добавляем строку с название класса с пространством имен:
'bootstrap' => [
    'log',
    'app\Bootstrap'
    ],

В данном случае я разместил класс в корне приложения Yii2 (basic). Для Advanced это стоило бы делать, например, в каталоге common.

В зависимости от места создания файла Bootstrap, может потребоваться обновить автозагрузчик Composera:
composer dump-autoload –o

Контейнер, автоматически, создает экземпляры зависимых объектов, вставляя их в создаваемый объект, настраивает и, наконец, возвращает вновь созданный объект.

Посмотреть методы для работы с контейнером (+ примеры использования) можно в файле vendor\yiisoft\yii2\di\Container.php.