njasm / container
PHP的依赖容器
Requires
- php: >=5.3
- container-interop/container-interop: ~1.0
Requires (Dev)
- aura/di: ~1.0
- illuminate/container: ~4.2
- joomla/di: ~1.2
- mnapoli/php-di: ~4.0
- nette/di: ~2.2
- orno/di: ~2.0
- phpunit/phpunit: 4.4.*@dev
- pimple/pimple: ~3.0
- ray/di: ~1.4
- satooshi/php-coveralls: dev-master
- symfony/dependency-injection: ~2.5
- zendframework/zend-di: ~2.0
This package is not auto-updated.
Last update: 2020-11-27 20:03:26 UTC
README
依赖容器/服务定位器
特性
- 支持别名服务键
- 循环依赖保护
- 原始数据类型注册
- 非注册服务的自动构造函数依赖解析和注入
- 懒加载和懒实例化方法
- 懒加载和懒实例化单例服务注册
- 支持服务实例化后进行公共设置器注入/方法调用
- 支持服务实例化后进行公共属性/属性注入
- 在调用
Container::get
时,可以通过提供新的来覆盖现有的依赖(属性和设置器)声明 - 支持嵌套提供者/容器
- 符合
Container-Interop
接口
要求
- PHP 5.3或更高版本。
安装
将njasm\container
包含到您的项目中,通过将其添加到composer.json
文件中。
{ "require": { "njasm/container": "~1.0" } }
使用
要创建一个容器,只需实例化Container
类。
use Njasm\Container\Container; $container = new Container();
使用别名
有时您的key
太长,不方便客户端代码使用,例如,当将一个interface
绑定到一个implementation
或使用类的FQCN作为key
时。
namespace Very\Long\Name\Space; interface SomeInterface {} class SomeImplementation implements SomeInterface { // code here } $container = new Njasm\Container\Container(); $container->set('Very\Long\Name\Space\SomeInterface', new SomeImplementation()); $container->alias('Some', 'Very\Long\Name\Space\SomeInterface'); $some = $container->get('Some');
定义服务
服务通过两个参数定义。一个key
和一个value
。您定义服务的顺序无关紧要。
定义服务 - 原始数据类型
$container->set("Username", "John"); echo $container->get("Username");
定义服务 - 绑定服务(懒加载)
您可以将一个key
绑定到一个可实例化的FCQNvalue
。
$container->bind("MyKey", "\My\Namespace\SomeClass");
如果您想绑定一个服务,并将其注册为Singleton
服务。
$container->bindSingleton("MyKey", "\My\Namespace\SomeClass");
both Container::bind
和Container::bindSingleton
使用懒加载方法,所以当请求MyKey
时,\My\Namespace\SomeClass
才会被评估/实例化。
当绑定服务时,可以声明构造函数依赖项,设置公共属性和调用带参数的方法,因此在实例化服务时进行注入/设置。
namespace \App\Actors; class Person { protected $name; protected $age = 24; public genre = 'Male'; public function __construct($name = 'John') { $this->name = $name; } public function getName() { return $this->name; } public function getAge() { return $this->age; } public function setAge($age) { $this->age = (int) $age; } } $container->bind( "Person", // key "\App\Actors\Person", // FQCN array("Jane"), // constructor dependencies array("genre" => "Female"), // attributes injection array("setAge" => array(33)) // call methods ); // binding with chaining methods $container->bind("Person", '\App\Actors\Person') ->setConstructorArguments(array("Jane")) // setConstructorArgument($index, $argument) ->setProperty("genre" => "Female") // setProperties(array("genre" => "Female", ...) also work ->callMethod("setAge", array(33)); // callMethods(array('methodName' => 'methodValue', ...)); // retrieving the object $person = $container->get("Person"); echo $person->getName(); // Jane echo $person->getAge(); // 33 echo $person->genre // Female // calling services and overriding declared dependencies $person2 = $container->get( "Person", array("Mark"), array("genre" => "Male"), array("setAge" => array(55)) ); echo $person2->getName(); // Mark echo $person2->getAge(); // 55 echo $person2->genre // Male
定义服务 - 对象(懒加载)
$mailer = new \Namespace\For\My\MailTransport( "smtp.example.com", "username", "password", 25 ); $container->set( "Mail.Transport", $mailer, array(), // constructor args array(), // public properties injection array("withSSL" => array(false)) // calling methods ); $mailerTransport = $container->get("Mail.Transport");
对于set
定义,也可以覆盖已声明的现有依赖。
// calling methods and injecting attributes is also possible $mailerTransportSsl = $container->get( "Mail.Transport", array(), array(), array("withSSL" => array(true)) );
定义服务 - 复杂构建(懒加载)
有时候,您可能想实例化一个对象,但构建过程非常复杂,您希望控制这个过程。您可以使用匿名函数来实现。
$container->set( "Complex", function($firstName = "John", $lastName = "Doe") { // complex logic here // ... $theComplexObject = new Complex($firstName, $lastName); return $theComplexObject; } ); $complex = $container->get("Complex"); // injecting closure dependencies is also possible $complexJane = $container->get("Complex", array("Jane", "Fonda"));
定义服务 - 具有嵌套依赖的复杂构建(懒加载)
嵌套依赖的创建也是可能的。您只需将容器传递给闭包即可。
$container->set( "Mail.Transport", function() use (&$container) { return new \Namespace\For\My\MailTransport( $container->get("Mail.Transport.Config") ); } ); $container->set( "Mail.Transport.Config", function() { return new \Namespace\For\My\MailTransportConfig( "smtp.example.com", "username", "password", 25 ); } ); $mailer = $container->get("Mail.Transport");
定义单例服务
对于注册单例服务,您使用单例方法调用。
$container->singleton( "Database.Connection", function() { return new \Namespace\For\My\Database( "mysql:host=example.com;port=3306;dbname=your_db", "username", "password" ); } ); // MyDatabase is instantiated and stored, for future requests to this service, // and then returned. $db = $container->get("Database.Connection"); $db2 = $container->get("Database.Connection"); // $db === $db2 TRUE
定义子/嵌套容器
只要您使用现有的容器适配器为您的应用程序现有的容器,就可以嵌套容器。适配器类必须实现 ServicesProviderInterface
,更多示例请参阅 Adapter
文件夹。
$pimple; // is your instantiated pimple container $pimple["Name"] = $pimple->factory(function() { return "John"; } $pimpleAdapter = new \Njasm\Container\Adapter\PimpleAdapter($pimple); $mainContainer = new \Njasm\Container\Container(); $mainContainer->provider($pimpleAdapter); $mainContainer->has("Name"); // TRUE echo $mainContainer->get("Name"); // John
服务的自动解析
当容器被请求一个未注册的服务时,它会尝试找到该类,并自动尝试解析您类的构造函数依赖项。
namespace My\Name\Space; class Something { // code } // without registering the Something class in the container you can... $container = new Njasm\Container\Container(); $something = $container->get('My\Name\Space\Something'); //$something instanceof 'My\Name\Space\Something' == true //once again you can also inject dependencies when calling get method. $something = $container->get( "My\Name\Space\Something", array("constructor value 1", "constructor value 2"), array("attributeName" => "value 1"), // attributes array("methodName" => array("value 1", "value 2")) );
路线图
不分先后 - 检查里程碑以获得更有序的视图。
- 从配置文件中加载定义
- 优化
贡献
您想帮助开发新功能/通过重构等改进现有代码吗?或者想讨论一个功能/错误/想法?只要您遵循一些PR指南,问题和拉取请求都欢迎
拉取请求必须
- 符合PSR-2规范。
- 在您的拉取请求中提交测试以验证您的更改/新代码的引入。
- 享受乐趣。