stg/ieu_container

ieUtilities - 依赖容器

2.0.1 2017-06-14 12:22 UTC

This package is auto-updated.

Last update: 2024-08-27 02:55:42 UTC


README

PHP依赖注入容器,灵感来源于AngularJS注入器和Pimple\Container

用法

use ieu\Container\Container;

$container = (new Container())
	->value('factor', 2)
	->service('multiplier', ['factor', 'Vendor\\Project\\Multiplier'])
	->factory('double', ['multiplier', function($theMultiplierService){
		return function($number) use ($theMultiplierService) {
			return $multiplierServcie->multiply($number);
		};
	}]);

echo $container['factor']; // 2
echo $container['double'](10); // 20

注入

依赖可以通过使用依赖数组 ['dependencyA', 'dependencyB', $callableOrClassname] 注入到服务和工厂中,其中依赖将作为参数传递给可调用对象或类构造函数。

function some_function($A) {
	echo "function: $A";
}

class Foo {
	public static function bar($A) {
		echo "static method: $A";
	}

	public function baz($A) {
		echo "method: $A";
	}
}

$object = new Foo;

// Setup container

$container = (new Container)
	// Add some content
	->value('A', 'Some value')
	->value('InnerCallbackObject', $object)
	->value('InnerCallbackClosure', function($A){
		echo "inner: $A";
	})

	// Case 1: Closure
	->factory(['A', function($A) {
			echo "closure $A";
		}])

	// Case 2: Function
	->factory('Function', ['A', 'some_function'])

	// Case 3: Static method
	->factory('Static1',  ['A', [Foo::CLASS, 'bar']])

	// Case 4: Static method variant
	->factory('Static2',  ['A', Foo::CLASS . '::bar'])

	// Case 5: Public method
	->factory('Public',   ['A', [$object, 'baz']])

	// Case 7: Container internal callback object
	->factory('Inner',    ['A', ['InnerCallbackObject', 'baz']])

	// Case 7: Container internal callback closure
	->factory('Inner',    ['A', ['InnerCallbackClosure']])

另一种(较慢)方式是使用可调用或构造函数的参数名来指定依赖。例如,function($dependencyA, $dependencyB) {...}['dependencyA', 'dependencyB', function($depA, $depB) { /*...*/ }] 有相同的结果。

注意:这不会在内部回调中工作!

常量

可以使用 self ieu\Container\Container::constant(string $name, mixed $value) 方法定义常量。

注意:常量在提供者配置周期中可用!

可以使用 self ieu\Container\Container::value(string $name, mixed $value) 方法定义值。

$container = (new Container)
	->value('A', 'Value');

工厂

可以使用 self ieu\Container\Container::factory(string $name, mixed $factory) 方法定义工厂。

$container = (new Container)
	->value('DependencyA', 'Value')

	// With dependency hint
	->factory('Name', ['DependencyA', function($a) {
		echo $a; // Value
	}])

	// Auto resolve
	->factory('Name', function($DependencyA) {
		echo $DependencyA; // Value
	}]);

服务

可以使用 self ieu\Container\Container::service(string $name, mixed $service) 方法定义服务。服务方法期望一个类名或一个以类名为最后一个元素的依赖数组作为参数。例如,['dependencyA', 'dependencyB', 'Vendor\\Project\\Service'] 或仅仅是(较慢的)'Vendor\\Project\\Service',其中构造函数的参数名用于注入依赖。

class Foo {
	public function __construct($DependencyA) {
		echo $DependencyA; // Value
	}
}

$container = (new Container)
	->value('DependencyA', 'Value')

	// With dependency hint
	->factory('Name', ['DependencyA', Foo::CLASS])
	
	// Auto resolve
	->factory('Name', Foo::CLASS);

装饰器

您可以使用 self ieu\Container\Container::decorator(string $name, mixed $decorator) 方法来覆盖现有依赖,同时接收原始实例作为局部依赖。装饰器必须是 factoryprovider

$container = (new Container)
	->factory('SomeName', [function(){
		return 'Hello';
	}])
	->decorator('SomeName', ['DecoratedInstance', function($org) {
		return $org . 'World';
	}]);

echo $container['SomeName']; // HelloWorld

提供者

提供者可以是任何具有公共属性 factory 的对象,该属性描述了作为 依赖数组 的工厂。可以使用 self ieu\Container\Container::provider(string $name, object $provider) 方法设置提供者。

在配置过程中可以通过使用带 Provider 后缀的名称作为依赖来访问提供者。

class PrefixerProvider {
	private $prefix = 'Hello';

	public $factory;

	public function __construct()
	{
		$this->factory = ['Name', [$this, 'factory']];
	}

	public function setPrefix(string $prefix) : void
	{
		$this->prefix = $prefix;
	}

	public function factory(string $name) : string
	{
		return sprtinf('%s %s', $this->prefix, $name);
	}
}


$container = (new Container)
	->factory('Name', [function(){
		return 'Justus';
	}])
	->provider('PrefixedName', new PrefixerProvider))
	->config(['PrefixedNameProvider', function($provider) {
		$provider->setPrefix('Goodbye');
	}]);

echo $container['PrefixedName']; // Goodbye Justus