moddengine/dice

一个针对PHP 7.1+ 和 PHP 8.0+的极简依赖注入容器(DIC)。

v4.1.6 2022-10-25 00:06 UTC

README

Build Status

请注意:这个版本是一个分支,提供了一些尚未合并到由Tom Butler维护的原版仓库中的修复。

Dice是一个针对PHP的极简依赖注入容器,注重轻量级、快速,尽可能减少配置。

项目目标

  1. 保持轻量级,不是一个包含数十个文件的庞大库(Dice是一个单个类),但支持所有功能(以及更多)比复杂容器提供的功能。

  2. “只需工作”。基本功能应在不进行任何配置的情况下工作。

  3. 当需要配置时,它应该尽可能少、可重用,并且易于使用。

  4. 速度!(请参阅性能部分

安装

只需将轻量级的Dice.php包含到您的项目中,即可使用而无需任何其他配置。

简单示例

<?php
class A {
	public $b;

	public function __construct(B $b) {
		$this->b = $b;
	}
}

class B {

}

require_once 'Dice.php';
$dice = new \Dice\Dice;

$a = $dice->create('A');

var_dump($a->b); //B object

?>

完整文档

有关完整文档,请参阅Dice PHP Dependency Injection container 主页

PHP版本兼容性

Dice与PHP 7.1+ 和 PHP 8.0+兼容。

性能

Dice使用反射,这通常被错误地标记为“慢”。反射比加载和解析配置文件要快得多。这里有一些基准测试更多基准测试(要下载基准测试工具,请参阅此存储库)并且Dice在大多数情况下比其他容器快。

在实际世界测试中(测试6),Dice与Pimple(需要编写大量的配置代码)并驾齐驱,尽管Symfony\DependencyInjection在创建对象方面更快,但它有更大的开销,并且您需要在每次页面加载时创建超过500个对象,直到它比Dice快。Phalcon的情况也是如此,加载Phalcon扩展的开销意味着除非您在每个HTTP请求中创建超过一千个对象,否则开销不值得。

致谢

最初由Tom Butler (@TomBZombie) 开发,感谢daniel-meister (@daniel-meister)、Garrett W. (@garrettw)、maxwilms (@maxwilms) 对错误修复、建议和改进。

更新

2021年1月25日 4.1版本发布 - PHP 8支持

Dice现在提供了基本的PHP 8支持,但尚未解决联合类型。

2018年11月15日 4.0版本发布 - 不兼容

Dice现在是不可变的,并且对其他不可变对象的支持更好。

新功能

1. Dice是不可变的

这避免了有关可变性的问题,其中Dice实例在应用程序中传递并被重新配置。唯一的区别是addRulesaddRule返回一个带有更新规则的新Dice实例,而不是更改现有实例的状态。

// Pre-4.0 code:
$dice->addRule('PDO', ['shared' => true]);

$db = $dice->create('PDO');

// 4.0 code:
$dice = $dice->addRule('PDO', ['shared' => true]);

$db = $dice->create('PDO');

从实际角度出发,在大多数情况下,只需在任意 $dice->addRule() 调用前加上 $dice = 即可,其效果与之前相同。

2. 对象方法链支持

一些不可变对象的一个特性是它们提供了对象链式调用。

考虑以下对象

$httpRequest = new HTTPRequest();
$httpRequest = $httpRequest->url('http://example.org')->method('POST')->postdata('foo=bar');

在之前的版本中,Dice 无法构建配置对象。从 4.0 版本开始,Dice 支持使用 call 规则和 Dice::CHAIN_CALL 常量进行方法链式调用。

$dice = $dice->addRule('HTTPRequest',
                ['call' => [
                    ['url', ['http://example.org'], Dice::CHAIN_CALL],
                    ['method', ['POST'], Dice::CHAIN_CALL ],
                    ['postdata', ['foo=bar'], Dice::CHAIN_CALL]
                 ]
                ]
);

Dice 将用链式调用的结果替换 HTTPRequest 对象。这对于工厂类也很有用。

$dice = $dice->addRule('MyDatabase',
                [
                	'instanceOf' => 'DatabaseFactory',
                	'call' => [
                		['get', ['Database'], Dice::CHAIN_CALL]
                 ]
                ]
);

$database = $dice->create('MyDatabase');
//Equivalent of:

$factory = new DatabaseFactory();
$database = $factory->get('Database');

2018年6月3日 3.0 版本发布 - 与旧版本不兼容

新功能

1. 优先使用新的 addRules 方法,已移除 JSON 加载器。

$dice->addRules([
	'\PDO' => [
		'shared' => true
	],
	'Framework\Router' => [
		'constructParams' => ['Foo', 'Bar']
	]
]);

添加此功能是为了使 JSON 加载器变得冗余。从 JSON 文件中加载规则可以很容易地通过以下代码实现

$dice->addRules(json_decode(file_get_contents('rules.json')));

2. 更好的 JSON 文件支持:常量和超全局变量

为了提高对在外部 JSON 文件中定义的规则的支持,现在可以将常量和超全局变量传递给 Dice 创建的对象。

例如,将 $_SERVER 超全局变量传递给路由实例,并使用 PDO::setAttributePDO::ATTR_ERRMODE 以及 PDO::ERRMODE_EXCEPTION 来调用 PDO,在 JSON 文件中可以这样做

rules.json

{
	"Router": {
		"constructParams": [
			{"Dice::GLOBAL": "_SERVER"}
		]
	},
	"PDO": {
		"shared": true,
		"constructParams": [
			"mysql:dbname=testdb;host=127.0.0.1",
			"dbuser",
			"dbpass"
		],
		"call": [
					[
						"setAttribute",
						[
							{"Dice::CONSTANT": "PDO::ATTR_ERRMODE"},
							{"Dice::CONSTANT": "PDO::ERRMODE_EXCEPTION"}
						]
					]
		]
	}
}
$dice->addRules(json_decode(file_get_contents('rules.json')));

与旧版本不兼容的更改

  1. Dice 3.0 需要 PHP 7.0 或更高版本,不再支持 PHP 5.6。

  2. Dice 不再支持用 'instance' 键表示实例。例如

$dice->addRule('ClassName', [
	'constructParams' => ['instance' => '$NamedPDOInstance']
]);

如问题 #125 中所述,这导致如果数组具有 'instance' 键,则无法将数组传递给构造函数。相反,应使用新的 \Dice\Dice::INSTANCE 常量

$dice->addRule('ClassName', [
	'constructParams' => [\Dice\Dice::INSTANCE => '$NamedPDOInstance']
]);

为了使常量更容易输入,可以 use \Dice\Dice; 并引用 Dice::INSTANCE

10/06/2016

** 与旧版本不兼容的更改 **

基于 问题 110,现在使用 instanceOf 命名的实例将继承它们所属类的规则

$rule = [];
$rule['shared'] = true;

$dice->addRule('MyClass', $rule);

$rule = [];
$rule['instanceOf'] = 'MyClass';
$rule['constructParams'] = ['Foo', 'Bar'];

$dice->addRule('$MyNamedInstance', $rule);

$dice->create('$MyNamedInstance') 现在将创建一个遵循 MyClass$MyNamedInstance 应用的规则的类,因此实例将是共享的。

之前只使用命名实例应用的规则。

要恢复旧行为,请将命名实例上的 inherit 设置为 false

$rule = [];
$rule['shared'] = true;

$dice->addRule('MyClass', $rule);

$rule = [];
$rule['instanceOf'] = 'MyClass';
$rule['constructParams'] = ['Foo', 'Bar'];


//Prevent the named instance inheriting rules from the class named in `instanceOf`:
$rule['inherit'] = false;

$dice->addRule('$MyNamedInstance', $rule);

29/10/2014

  • 基于 问题 #15,Dice 现在将仅调用封装在 \Dice\Instance 中的闭包。**请注意:这是与旧版本不兼容的**。

之前 Dice 会运行作为替换、constructParams 以及调用方法时传递的闭包

$rule->substitutions['A'] = function() {
	return new A;
};

$rule->call[] = ['someMethod', function() {
// '2' will be provided as the first argument when someMethod is called
return 2;
}];

$rule->constructParams[] = function() {
	//'abc' will be providedas the first constructor parameter
	return 'abc';
};

由于闭包始终被调用和执行,因此这种行为已更改,使得无法提供作为构造参数或调用方法时的闭包,因为闭包始终被调用和执行。

为了克服这一点,Dice 现在将仅在闭包封装在 \Dice\Instance 中时调用闭包

$rule->substitutions['A'] = ['instance' => function() {
	return new A;
}];

$rule->call[] = ['someMethod', ['instance' => function() {
// '2' will be provided as the first argument when someMethod is called
return 2;
}]]);

$rule->constructParams[] =  ['instance' => function() { {
	//'abc' will be providedas the first constructor parameter
	return 'abc';
}]);

04/09/2014

  • 发布 PHP5.6 分支。这稍微更有效率,因为它使用了 PHP5.6 的特性。对于 PHP5.4-PHP5.5,请参阅相关分支。此版本将在 PHP5.6 更广泛时维护。

26/08/2014

  • 添加 PHP5.6 分支。通过使用 PHP5.6 特性整理代码。当 PHP5.6 发布时,这将移动到 master 分支。

28/06/2014

  • 大大提高了效率。现在 Dice 是最快的 PHP 依赖注入容器!

06/06/2014

27/03/2014

  • 移除 assign() 方法,因为它可以通过使用 $rule->shared 来提供相同的功能
  • 移除 $dice->create() 中的 $callback 参数,因为此功能的唯一真正用途可以更好地使用 $rule->shareInstances 实现
  • 整理代码,删除未使用或未记录的特性。Dice 现在更轻量级且更快。
  • 修复了一个bug,该bug在调用$rule->call时,会使用构造函数中的替换规则在每个方法调用上
  • 更新了Dice文档,以使用简写数组语法

01/03/2014

  • 为Xml Loader和Loader Callback类添加了测试用例
  • 添加了一个JSON loader + 测试用例
  • 将所有测试用例添加到一个测试套件中
  • 迁移到PHP5.4数组语法。PHP5.3兼容版本现在可在PHP5.3分支中找到。
  • 修复了一个问题,即每次创建类时,使用命名实例会触发无效类名的自动加载器

28/02/2014

  • 添加了基本的命名空间支持。文档更新将很快跟进。此外,已将XML loader移动到自己的文件中,如果您使用它,则需要单独包含。
  • 请注意:变更不向后兼容。但是,通过以下查找/替换操作可以轻松修复:
	new Dice => new \Dice\Dice
	new DiceInstance => new \Dice\Instance
	new DiceRule => new \Dice\Rule