kaspi / di-container
Dependency injection container with autowired
Requires
- php: ^8.0 || ^8.1 || ^8.2 || ^8.3 || ^8.4
- ext-tokenizer: *
- psr/container: ^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.41
- mikey179/vfsstream: ^1.6
- phpstan/phpstan: ^2.1
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^9.6
- dev-main
- v4.0.x-dev
- v3.13.x-dev
- v3.13.0
- v3.12.1
- v3.12.0
- 3.11.0
- v3.10.2
- v3.10.1
- v3.10.0
- v3.9.3
- v3.9.2
- v3.9.1
- v3.9.0
- v3.8.0
- v3.7.1
- v3.7.0
- v3.6.3
- v3.6.2
- v3.6.1
- v3.6.0
- v3.5.1
- v3.5.0
- v3.4.1
- v3.4.0
- v3.3.0
- v3.2.0
- v3.1.0
- v3.0.1
- v3.0.0
- v2.8.0
- v2.7.9
- v2.7.8
- v2.7.7
- v2.7.6
- v2.7.5
- v2.7.4
- v2.7.3
- v2.7.2
- v2.7.1
- v2.7.0
- v2.6.2
- v2.6.1
- v2.6.0
- v2.5.0
- v2.4.0
- v2.3.1
- v2.3.0
- v2.2.3
- 2.2.2
- v2.2.1
- v2.2.0
- v2.1.1
- v2.1.0
- v2.0.4
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- v1.7.0
- v1.6.3
- v1.6.2
- v1.6.1
- v1.6.0
- v1.5.0
- v1.4.0
- v1.3.0
- v1.2.1
- v1.2.0
- v1.1.1
- v1.1.0
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- dev-4.0.x/62-compiling-container
- dev-202-closure-parser
- dev-4.0.x/196-normalize-definitions-via-dicontainergetdefinitions
- dev-4.0.x/197-resolve-container-identifier-via-diget-or-didefinitionget
This package is auto-updated.
Last update: 2025-04-01 16:32:12 UTC
README
Kaspi/di-container — это легковесный контейнер внедрения зависимостей для PHP >= 8.0.
Установка
composer require kaspi/di-container
Особенности
- Autowire - контейнер автоматически создаёт и внедряет зависимости.
- Поддержка "zero configuration for dependency injection" - когда ненужно объявлять зависимость в определениях контейнера. Если класс не имеет зависимостей или зависит только от других конкретных классов, контейнеру не нужно указывать, как разрешить этот класс.
- Поддержка Php-атрибутов для конфигурирования сервисов в контейнере.
- Поддержка тегов (tags) для определений и сервисов в контейнере.
Быстрый старт
Определения классов:
// src/Services/Envelope.php namespace App\Services; // Класс для создания сообщения class Envelope { public function subject(string $subject): static { // ... return $this; } public function message(string $message): static { // ... return $this; } }
// src/Services/Mail.php namespace App\Services; // Сервис отправки почты class Mail { public function __construct(private Envelope $envelope) {} public function envelop(): Envelope { return $this->envelope; } public function send(): bool { // отправка сообщения } }
// src/Models/Post.php namespace App\Models; // Модель данных — пост в блоге. class Post { public string $title; // ... }
// src/Controllers/PostController.php namespace App\Controllers; use App\Services\Mail; use App\Models\Post; // Контроллер для обработки действия. class PostController { public function __construct(private Mail $mail) {} public function send(Post $post): bool { $this->mail->envelop() ->subject('Publication success') ->message('Post <'.$post->title.'> was published.'); return $this->mail->send(); } }
use App\Controllers\PostController; use App\Models\Post; use Kaspi\DiContainer\DiContainerFactory; // Создать контейнер. $container = (new DiContainerFactory())->make(); // more code... //Заполняем модель данными. $post = new Post(); $post->title = 'Publication about DiContainer'; // получить класс PostController с внедренным сервисом Mail и выполнить метод "send" $postController = $container->get(PostController::class); $postController->send($post);
Note
Контейнер "пытается" самостоятельно определить запрашиваемую зависимость - является ли это классом или callable типом.
DiContainer
выполнит следующие действия для App\Controllers\PostController
:
$post = new App\Controllers\PostController( new App\Services\Mail( new App\Services\Envelope() ) );
Tip
Реализация кода в примере
Другой вариант для примера выше можно использовать для получения результата DiContainer::call()
:
use App\Controllers\PostController; use App\Models\Post; $post = new Post(); $post->title = 'Publication about DiContainer'; // ... // получить класс PostController с внедренным сервисом Mail и выполнить метод "send" $container->call( definition: [PostController::class, 'send'], arguments: ['post' => $post] );
Tip
Больше информации о DiContainer::call()
Note
Примеры использования пакета kaspi/di-container в репозитории
Конфигурирование DiContainer
Для конфигурирования контейнера используется класс
Kaspi\DiContainer\DiContainerConfig::class
который реализует интерфейс
Kaspi\DiContainer\Interfaces\DiContainerConfigInterface
use Kaspi\DiContainer\{DiContainerConfig, DiContainer}; $diConfig = new DiContainerConfig( // Ненужно объявлять каждую зависимость. // Если класс, функция или интерфейс существуют // и может быть запрошен через автозагрузку (например через composer), // то объявлять каждое определение необязательно. useZeroConfigurationDefinition: true, // Использовать Php-атрибуты для конфигурирования зависимостей контейнера. useAttribute: true, // Возвращать всегда одни и тот же объект (singleton pattern). isSingletonServiceDefault: false, ); // передать настройки в контейнер $container = new DiContainer(config: $diConfig);
DiContainerFactory.
Можно использовать фабрику для создания контейнера с настроенными по умолчанию параметрами:
use Kaspi\DiContainer\DiContainerFactory; $container = (new DiContainerFactory())->make();
Конструктор фабрики:
DiContainerFactory::__construct( ?Kaspi\DiContainer\Interfaces\DiContainerConfigInterface $config = null )
Tip
Можно передать другую конфигурацию контейнера в фабрику.
Зарегистрировать сконфигурированные определения (сервисы) в контейнере:
DiContainerFactory::make( iterable $definitions = [] ): \Kaspi\DiContainer\Interfaces\DiContainerInterface
Note
Некоторые интерфейсы или классы всегда возвращают текущий контейнер зависимостей. При разрешении зависимости для интерфейсов и классов:
Psr\Container\ContainerInterface::class
Kaspi\DiContainer\Interfaces\DiContainerInterface::class
Kaspi\DiContainer\DiContainer::class
будет получен текущий class Kaspi\DiContainer\DiContainer::class
use Kaspi\DiContainer\DiContainerFactory; function testFunc(\Psr\Container\ContainerInterface $c) { return $c; } $container = (new DiContainerFactory())->make(); var_dump($container->call('testFunc') instanceof DiContainer); // true
use Kaspi\DiContainer\DiContainerFactory; use Psr\Container\ContainerInterface; class TestClass { public function __construct( public ContainerInterface $container ) {} } $container = (new DiContainerFactory())->make(); var_dump($container->get(TestClass::class)->container instanceof DiContainer); // true
📁 DefinitionsLoader
Собирает определения для контейнера зависимостей из разных конфигурационных файлов (dependency definitions), и выполняет "импорт" классов из директорий.
Подробное описание использования DefinitionsLoader.
🧰 Подробное описание конфигурирования и использования
- 🐘 DiContainer с конфигурированием в стиле php определений.
- #️⃣ DiContainer c конфигурированием через PHP атрибуты.
- 📦 DiContainer::call() для вызова чистых
callable
типов и дополнительных определений. - 🔖 Тэгирование определений и сервисов.
Тесты
Прогнать тесты без подсчёта покрытия кода
composer test
Запуск тестов с проверкой покрытия кода тестами
./vendor/bin/phpunit
Статический анализ кода
Для статического анализа используем пакет PHPStan.
composer stat
./vendor/bin/phpstan
Code style
Для приведения кода к стандартам используем php-cs-fixer который объявлен в dev зависимости composer-а
composer fixer
Использование Docker образа с PHP 8.0, 8.1, 8.2, 8.3, 8.4
Указать образ с версией PHP можно в файле .env
в ключе PHP_IMAGE
.
По умолчанию контейнер собирается с образом php:8.0-cli-alpine
.
Собрать контейнер
docker-compose build
Установить зависимости php composer-а:
docker-compose run --rm php composer install
🔔 Если установлен make
в системе:
make install
Тесты
Запуск тестов без отчёта о покрытии кода:
docker-compose run --rm php vendor/bin/phpunit --no-coverage
🔔 Если установлен make
в системе:
make test
Прогнать тесты с отчётом о покрытии кода:
docker-compose run --rm php vendor/bin/phpunit
🔔 Если установлен make
в системе:
make test-cover
⛑ pезультаты будут в папке
.coverage-html
Статический анализ кода PHPStan
docker-compose run --rm php vendor/bin/phpstan
если установлен make
в системе:
make stat
Запуск комплексной проверки
Если установлен make
– запуск проверки code-style, stat analyzer, tests:
make all
Другое
Можно работать в shell оболочке в docker контейнере:
docker-compose run --rm php sh