Разрешение зависимостей
После регистрации зависимостей, вы можете использовать контейнер внедрения зависимостей для создания новых объектов, и контейнер автоматически разрешит зависимости их экземпляра и их внедрений во вновь создаваемых объектах. Разрешение зависимостей рекурсивно, то есть если зависимость имеет другие зависимости, эти зависимости также будут автоматически разрешены.
Вы можете использовать [[yii\di\Container::get()]] для создания или получения объектов. Метод принимает имя зависимости, которым может быть имя класса, имя интерфейса или псевдоним. Имя зависимости может быть зарегистрировано через set()
или setSingleton()
. Вы можете опционально предоставить список параметров конструктора класса и конфигурацию для настройки созданного объекта.
Например:
// "db" ранее зарегистрированный псевдоним
$db = $container->get('db');
// эквивалентно: $engine = new \app\components\SearchEngine($apiKey, ['type' => 1]);
$engine = $container->get('app\components\SearchEngine', [$apiKey], ['type' => 1]);
За кулисами, контейнер внедрения зависимостей делает гораздо больше работы, чем просто создание нового объекта. Прежде всего, контейнер, осмотрит конструктор класса, чтобы узнать имя зависимого класса или интерфейса, а затем автоматически разрешит эти зависимости рекурсивно.
Следующий код демонстрирует более сложный пример. Класс UserLister
зависит от объекта, реализующего интерфейс UserFinderInterface
; класс UserFinder
реализует этот интерфейс и зависит от объекта Connection
. Все эти зависимости были объявлены через тип подсказки параметров конструктора класса. При регистрации зависимости через свойство, контейнер внедрения зависимостей позволяет автоматически разрешить эти зависимости и создаёт новый экземпляр UserLister
простым вызовом get('userLister')
.
namespace app\models;
use yii\base\Object;
use yii\db\Connection;
use yii\di\Container;
interface UserFinderInterface
{
function findUser();
}
class UserFinder extends Object implements UserFinderInterface
{
public $db;
public function __construct(Connection $db, $config = [])
{
$this->db = $db;
parent::__construct($config);
}
public function findUser()
{
}
}
class UserLister extends Object
{
public $finder;
public function __construct(UserFinderInterface $finder, $config = [])
{
$this->finder = $finder;
parent::__construct($config);
}
}
$container = new Container;
$container->set('yii\db\Connection', [
'dsn' => '...',
]);
$container->set('app\models\UserFinderInterface', [
'class' => 'app\models\UserFinder',
]);
$container->set('userLister', 'app\models\UserLister');
$lister = $container->get('userLister');
// что эквивалентно:
$db = new \yii\db\Connection(['dsn' => '...']);
$finder = new UserFinder($db);
$lister = new UserLister($finder);