substancephp / container
一个用于PHP的PSR-11 IoC容器
v0.6.0
2024-09-29 21:46 UTC
Requires
- php: >=8.3
- ext-xdebug: *
- psr/container: ^2.0
Requires (Dev)
- phpstan/phpstan: ^1.11
- phpunit/phpunit: ^11.0
- squizlabs/php_codesniffer: *
README
概述
substancephp/container
是一个PHP的依赖注入包。它提供以下功能:
- 实现 PSR-11容器接口 的容器类
- 容器继承机制
- 使用类型提示或属性自动将参数注入闭包中
- 可选的自动装配
安装
composer require substancephp/container
用法
以下是一个示例代码段,展示如何使用 SubstancePHP\Container
类定义注入的依赖项。
use Laminas\Diactoros\ServerRequestFactory; use Psr\Http\Message\ServerRequestInterface; use SubstancePHP\Container\Container; use SubstancePHP\Container\Inject; // Initialize a `Container` instance from an array. The keys are strings (typically, but not necessarily, // class names), and the values are callbacks telling the container how to construct that dependency. $container = Container::from([ // Example of "manual" definition Foo::class => fn () => new Foo('example', 'constructor', 'parameters'), // The callback optionally takes a parameter, referring to the Container instance itself. // This can be used to get other dependencies to be used in the callback. BarInterface::class => fn (Container $c) => new BarImplementation($c->get(Foo::class)), // The static `Container::autowire` method can be referenced to as a closure. It will arrange for the // construction of the given dependency instance using reflection on its constructor parameters. Baz::class => Container::autowire(...), // Example of a simple literal value. 'ttl-seconds' => fn () => 30, ]); // You can spawn a child container that inherits the parent container's definitions, // and augments/overrides them with additional definitions. This might be done, for example, // to initialize a separate `Container` instance per request. // Note that the *parent* container can be any instance of `Psr\Container\ContainerInterface`; // it need not be an instance of `SubstancePHP\Container\Container`. $container2 = Container::extend($container, [ ServerRequestInterface::class => fn () => ServerRequestFactory::fromGlobals(), ]); // A `Container` can be invoked to run an arbitrary callable, autowiring its parameters with // dependencies from the container: $container2->run(function( // Parameters of named, non-scalar types will be injected based on the class/interface/enum name: Foo::class $foo, ServerRequestInterface $request, // The `SubstancePHP\Container\Inject` attribute allows specifying the dependency to // be injected in the given parameter. This is useful especially when the parameter is // of a scalar type: #[Inject('ttl-seconds')] int $ttl, ): void { // ... do stuff }); // Similarly, if a class is autowired using Container::autowire(...), you can tell it use the Inject attribute // to specify dependencies for parameters that cannot be inferred automatically: public function __construct( Bar $bar, #[Inject('thing.xyz')] int $someParam, ) { }
注意,在首次查找给定的依赖项后,它将内部缓存在容器中,下一次将返回相同的实例。这种行为与Laravel的服务容器不同,后者默认情况下每次查找都返回一个新实例。
性能
substancephp/container
的目标是在符合PSR-11容器接口的同时提供一个非常简单但灵活的API界面。
该库的目标不是达到最高的运行时性能,而是足够好,足以满足绝大多数用例——我相信它确实做到了。