YetAnother DI — гибкий DI-контейнер, создающий экземпляры классов и их зависимости на основании параметров конструктора класса. Вам больше не потребуются конфиги, описания зависимостей, именование сервисов, или анонимные функции — всю информацию о связях контейнер будет брать из конструкторов. В отличии от популярных DI-контейнеров, данный контейнер работает только c Singletone'ами, т.е. с объектами, которые создаются 1 раз.
Рекомендуемая установка через composer:
{
"require": {
"yetanother/di": "dev-master"
}
}
use YetAnother\DI\Container;
$container = new Container();
$myObject = $container->get('MyClass');
// или
$myObject = $container['MyClass'];
При создании объекта, контейнер автоматически его сохраняет. Получение уже созданного объекта выполняется той же фунцией:
$myObject = $container->get('MyClass');
// или
$myObject = $container['MyClass'];
$container->has('MyClass'); // true/false
// или
isset($container['MyClass']);
$myObject = new MyClass();
$container->push($myObject);
// или
$container[] = $myObject;
// после добавления можно получить доступ к объекту по имени класса:
$container->get('MyClass') === $myObject; // true
$container->remove('MyClass');
// или
unset($container['MyClass']);
Допустим, класс MyModel зависит от класса Database, и эта зависимость описана в конструкторе:
class MyModel
{
private $db;
public function __construct(Database $db)
{
$this->db = $db;
echo 'MyModel created';
}
}
class Database()
{
public function __construct()
{
echo 'Database created';
}
}
Тогда, при создании объекта класса MyModel, сначала будет создан объект Database:
$myModel = $container->get('MyModel');
// Database created
// MyModel created
Но, если объект класа Database уже создан и хранится в контейнере, то он будет передан в конструктор MyModel, т.е. второй раз создаваться уже не будет:
$db = $container->get('Database');
// Database created
$myModel = $container->get('MyModel');
// MyModel created
Таким образом, создаются все зависимости по цепочке.
Если вам необходимы дополнительные действия при создании объектов, можно описать их в анонимной функции:
$container->set('Database', function () {
$db = new Database();
$db->connect();
return $db;
});
// или
$container['Database'] = function () {...};
Для того чтобы использовать объекты в анонимной функции, передайте их в качестве параметров функции:
$container->set('UserModel', function (Database $db, Session $session) {
...
});
Наряду с любыми объектами, вы можете использовать сам контейнер в качестве зависимости, но это делать не рекомендуется, т.к. при таком подходе сложно отследить связи между классами, а также усложняется процесс тестирования.
class MyClass
{
public function __construct(Container $container)
{
...
}
}
$container->set('MyClass', function (Container $container) {
...
});