IoC, 构造器依赖注入
Requires
- php: ^7.4|^8.0
- psr/container: ^1|^2
- psr/log: ^1|^2|^3
Requires (Dev)
- phpunit/phpunit: ^9.3
Provides
- psr/container-implementation: ^1|^2
This package is auto-updated.
Last update: 2024-09-03 15:30:19 UTC
README
配置更少,完成更多。
框架无关的依赖注入工具和PSR-11实现提供者。
要求
PHP 7.4|8+
安装
composer require free-elephants/di
使用
您的入口php脚本(index.php或某些后台作业运行器)
$components = require 'components.php'; $di = (new \FreeElephants\DI\InjectorBuilder)->buildFromArray($components); $app = $di->createInstance(\YourApplication::class); $app->run();
您的components.php
文件应包含依赖描述,如下所示
<?php return [ 'instances' => [ \PDO::class => new \PDO(getenv('DB_DNS'), getenv('DB_USER'), getenv('DB_PASS')), ], 'register' => [ \YourApplication::class, \ControllerFactory::class, \SomeService::class, \AnotherService::class, \Psr\Log\LoggerInterface::class => \Symfony\Component\Console\Logger\ConsoleLogger::class, ], 'callable' => [ // if function provided as key value // first argument passed to callable is psr container // second is key Foo::class => function(\Psr\Container\ContainerInterface $container, string $key) { return (new Foo())->setSomething($container->get('something')); }, // if array provided as key value // first argument passed to callable is psr container // remaining element as ...args tail Bar::class => [ // array where first element is callable, other is values for last arguments function(\Psr\Container\ContainerInterface $container, $firstArg, string $secondArg) { return new Bar($firstArg, $secondArg); }, 100, 500, ], ], 'loggers' => [ // For suitable logger injections use map, where keys are your services, that implement LoggerAwareInterface // and value is logger instances LoggerAwareClass::class => $logger, AnotherLoggerAwareClass::class => $anotherLogger, ], ];
主要思想:所有组件都应将所有依赖项作为构造器参数预期。所有其他工作委托给注入器。您不需要在代码中直接实例化任何类。您必须注入一些工厂。
通过环境覆盖组件
<?php // getenv('ENV') -> 'test' $components = (new \FreeElephants\DI\EnvAwareConfigLoader(__DIR__ . '/config', 'ENV'))->readConfig('components'); $di = (new \FreeElephants\DI\InjectorBuilder)->buildFromArray($components);
EnvAwareConfigLoader
加载 config/components.php
并与(如果存在)合并 config/components.test.php
。
选项
allowNullableConstructorArgs
默认值是 false
。
allowInstantiateNotRegisteredTypes
默认值是 false
。当您将其设置为 true
时,您只能注册特定接口的实例。所有最终类型依赖项将通过链式懒实例化!
useIdAsTypeName
默认值是 true
。
enableLoggerAwareInjection
默认值是 false
。
允许在构造后设置 LoggerInterface 到 LoggerAwareInterface 实例中,或如果存在类型,则使用日志记录器映射。
概念
(俄语)为PHP的简单构造器依赖注入
在面向对象中,可以根据其责任将类分为两大组:实体和服务的。
实体 包含数据和操作数据的方法。它们通常具有状态,并且在程序执行期间需要创建多个实例。例如
- 领域对象(例如 Doctrine 中的 Entities,Propel 中的 Models)
- 值对象
- 数据传输对象
- PSR 7 的 Request / Response
服务 负责其他所有事情
- 处理用户请求(控制器、命令)
- 操作实体
- 确保系统组件之间的通信
- 实例化其他实体和服务(工厂、定位器)
- 提供应用功能(协议、存储、路由)
服务通常需要单个实例,并且很少在执行期间改变其状态。服务可以在执行阶段之前描述,例如在静态文件中,并在代码中按需获取或创建一次。
实体不应依赖于服务。相反,服务通常操作实体实例,并且可能使用其他服务。
注入依赖的最明显和可靠的方式是构造器注入
- 无法创建一个未准备好的实例以供使用
- 类的依赖关系通过一个地方的定义合同
类型提示和 PHP 中的反射允许根据其构造器签名收集一个准备好的服务,而不需要额外的配置文件和魔法。这种方法在 free-elephants/di 中使用。这种方法很好地支持重构,因为它只使用原生的 PHP 代码,不需要在 yml、xml 或注释中静态描述依赖关系。