calgamo / di
Requires
- php: >=7.1
- ext-json: *
- calgamo/annotations: ~0.2
- calgamo/cache: ~0.2
- psr/container: ^1.0
Requires (Dev)
- calgamo/test: ^0.3
- mikey179/vfsstream: 1.3.*
- php-coveralls/php-coveralls: ^2.0
- phpunit/phpunit: ^6.3.0
- dev-master
- 0.6.0
- 0.5.0
- 0.4.0
- 0.3.8
- 0.3.7
- 0.3.6
- 0.3.5
- 0.3.4
- 0.3.3
- 0.3.2
- 0.3.1
- 0.3.0
- 0.2.0
- 0.1.31
- 0.1.30
- 0.1.29
- 0.1.28
- 0.1.27
- 0.1.26
- 0.1.25
- 0.1.24
- 0.1.23
- 0.1.22
- 0.1.21
- 0.1.20
- 0.1.19
- 0.1.18
- 0.1.17
- 0.1.16
- 0.1.15
- 0.1.14
- 0.1.13
- 0.1.12
- 0.1.11
- 0.1.10
- 0.1.9
- 0.1.8
- 0.1.7
- 0.1.6
- 0.1.5
- 0.1.4
- 0.1.3
- 0.1.2
- 0.1.1
- 0.1.0
This package is auto-updated.
Last update: 2019-11-19 21:02:52 UTC
README
描述
Calgamo/Di 是一个类似Pimple风格的依赖注入(DI)容器库。
特性
- Pimple风格API
- 懒加载以提高性能
- 多容器构建器
- 保护或限制组件
- 可缓存
- 为启动生成的动态代码
- 依赖注入
- 自动装配
- 构造函数、setter、字段注入
- 作用域:单例/原型
- 自定义注解
- @Inject
- @Scope
- @Singleton
- @Named
- @Prototype
要求
PHP 7.1 或更高版本
安装 calgamo/di
安装 calgamo/di 的推荐方式是通过 Composer。
composer require calgamo/di
安装后,您需要引入 Composer 的自动加载器
require 'vendor/autoload.php';
使用
1. 构建 Container
Container 可以通过构建器类直接创建。您可以选择您喜欢的创建 Container 的方式。
有几种构建 Container 的方法
- 简单(无容器构建器)
- Bootstrap 容器构建器
- 编译器容器构建器
- 模块化容器构建器
- 缓存编译器容器构建器
简单(无容器构建器)
您可以在不使用任何内置容器构建器的情况下构建 Container。
此方法简单且速度快,但使用多个组件时,Container 初始化代码将变得复杂。
use Calgamo\Di\Container; use Sample\Person; $container = Container(); $container['david'] = function(Container $c){ return new Person('David Smith', 24, 179.2, function($target){ return 'throws '.$target.'.'; }); }; $david = $container['david']; $david->sayHello(); // David Smith says "Hello! My name is David Smith. I am 24 years old."
Bootstrap 容器构建器
Bootstrap 容器构建器将通过回调函数(bootstrap)中编写的代码设置 Container。此方法非常快,但可能有些多余。
use Calgamo\Di\Container; use Calgamo\Di\BootstrapContainerBuilder; use Sample\Person; $bootstrap = function(Container $c){ $c['david'] = function(Container $c){ return new Person('David Smith', 24, 179.2, function($target){ return 'throws '.$target.'.'; }); }; }; $bulder = new BootstrapContainerBuilder($bootstrap); $container = $bulder->build(); $david = $container['david']; $david->sayHello(); // David Smith says "Hello! My name is David Smith. I am 24 years old."
编译器容器构建器
编译器容器构建器将通过配置文件(支持 .json/.yml/.php)设置 Container。此容器构建器在缓存目录中动态生成启动代码,因此第二次激活 Container 的时间将大大减少。
sample.php
use Calgamo\Di\CompilerContainerBuilder; use Calgamo\Config\Util\ConfigFileUtil; $config = ConfigFileUtil::loadConfigFromFile('components.json'); $container = (new CompilerContainerBuilder($config))->build(); $david = $container['david']; $david->sayHello(); // David Smith says "Hello! My name is David Smith. I am 24 years old."
components.json
{ "compiler": { "vendor_dir": "../vendor", "autoloaders": [ "../sample_autoloader2.php" ] }, "cache": { "root": "../cache", "filename": "sample_di" }, "components": [ { "id": "david", "type": "object", "class_name": "Sample\\Person", "injections": [ { "new": [ "David Smith", "@int: 24", "@float: 179.2", "@func: function($target){ return 'throws '.$target.'.'; }" ] } ] } ] }
@ 指令
如上配置文件(components.json),您可以在组件配置文件中使用 '@xxx' 指令。
以下有一些 '@xxx' 指令。
指令 | 替换 | 示例 |
---|---|---|
@id: [component_id] | 其他通过 [component_id] 识别的组件 | @id: logger |
@func: [function_code] | [function_code] | @func: function($a) { echo $s; } |
@int: [integer_value] | [integer_value] | @int: 100 |
@float: [float_value] | [float_value] | @float: 3.14 |
@bool: [bool_value] | [bool_value]('yes' 或 '1' 或 'on' 视为真) | @bool: yes @bool: true |
@json: [json_data] | 解码后的json | @json: { 'age': '21', 'name': 'david' } |
@env: [key] | $_ENV值($_ENV['key']) | @env: USER |
模块化容器构建器
模块化容器构建器将通过安装 "容器模块" 来设置容器。容器模块是一组容器初始化代码。
BootstrapContainerBuilder只提供一套初始化代码,但ModularContainerBuilder在需要时可以接受多个模块。
use Calgamo\Di\Container; use Calgamo\Di\ModularContainerBuilder; use Calgamo\Di\ContainerModuleInterface; use Sample\Person; class DavidModule implements ContainerModuleInterface { public function install(Container $container) { $container['david'] = function(){ return new Person('David Smith', 24, 179.2, function($target){ return 'throws '.$target.'.'; }); }; } } $builder = new ModularContainerBuilder([ new DavidModule() ]); $container = $builder->build(); $david = $container['david']; $david->sayHello(); // David Smith says "Hello! My name is David Smith. I am 24 years old."
2. 使用容器
get
// get service $service = $container['my-service']; // do something $service->doSomething();
set/unset
您可以用相同的方式在容器中设置实例或值。您还可以设置用于生成实例的工厂代码或用于懒加载的常量值。
// set object $container['my-favorite-fruits'] = new MyService(); // set object factory(lazy creation) $container['my-service'] = function(){ return new MyService(); }; // set constant value $container['my-favorite-fruits'] = [ 'apple', 'banana' ]; // set constant value factory(lazy creation) $container['my-service'] = function(){ return [ 'apple', 'banana' ]; }; // unset entry unset($container['my-favorite-fruits']);
slot
槽位是关于容器组件的信息。您可以通过槽位对象锁定或限制组件。
// get slot object $slot = $contianer->slot('something'); // lock the slot(in this case, 'something' slot will be locked) $slot->lock(); // type restriction $slot->mustBeTypeOf('array'); // instance-of restriction $slot->mustBeInstanceOf('MyServiceInterface');
提示
每次访问获取新实例
默认情况下,容器在第二次访问后返回现有对象。但您可以通过调用Container#newInstance()方法为每次访问检索新对象。
$cart = $container['cart']; echo 'count:' . $cart->countItems(); // count: 0 $cart->addItem('apple'); echo 'count:' . $cart->countItems(); // count: 1 $cart = $container['cart']; echo 'count:' . $cart->countItems(); // count: 1 $cart = $container->newInstance('cart'); echo 'count:' . $cart->countItems(); // count: 0
保护组件
您可以通过使用Slot#lock()方法来保护组件。
$container['cart'] = new MyCart(); // lock slot $container->slot('cart')->lock(); // this will fail becasue the slot is locked $container['cart'] = new AnotherCart(); // throws SlotIsLockedException
限制组件类型
您可以通过使用Slot#mustBeTypeOf()方法来限制组件类型。
$container['something'] = new MyCart(); // restrict slot to array value $container->slot('something')->mustBeTypeOf('array'); // this will fail because AnotherCart is not array $container['something'] = new AnotherCart(); // throws SlotTypeRestrictionViolationException // array value can be set $container['something'] = [ 'apple', 'banana' ];
限制组件类或接口
您可以通过使用Slot#mustBeInstanceOf()方法来限制组件类或接口。
$container['something'] = new MyCart(); // restrict slot to array value $container->slot('something')->mustBeInstanceOf('MyServiceInterface'); // this will fail because AnotherCart does not implement MyServiceInterface $container['something'] = new AnotherCart(); // throws SlotInstanceOfRestrictionViolationException // interface implemented instance can be set in this slot $container['something'] = new MyService; // class MyService implements MyServiceInterface
扩展组件
您可以通过使用Container#extend()方法来扩展组件。
// register my service $container['my_service'] = new MyService(); // extend my serice(set max item count) $container->extend('my_service', function($my_service) { $my_service->setMaxItems(10); }); echo 'max: ' . $container['my_service']->getMaxItems(); // max: 10 // register array $container['my_favorite_fruits'] = ['apple']; // add banana to my favorites array $container->extend('my_favorite_fruits', function(&$favorites) { $favorites[] = 'banana'; }); echo implode(', ',$container['my_favorite_fruits']); // apple, banana
编译器配置文件格式 & 参数
编译器配置文件可以以json、YAML和PHP格式编写。所有参数必须以数组元素开始。
组件配置文件:json格式示例
{ "compiler": { "vendor_dir": "../vendor", "autoloaders": [ "../sample_autoloader2.php" ] }, "cache": { "root": "../cache", "filename": "sample_di" }, "slots": [ { "id": "david", "type": "object", "instanceOf": "\\Sample\\PersonInterface", "locked": true } ], "components": [ { "id": "david", "type": "object", "class_name": "Sample\\Person", "injections": [ { "new": [ "David Smith", "@int: 24", "@float: 179.2", "@func: function($target){ return 'throws '.$target.'.'; }" ] } ] } ] }
组件配置文件:YAML格式示例
compiler: vendor_dir: "../vendor" autoloaders: "../sample_autoloader2.php" cache: root: "../cache", filename: sample_di slots: - id: david, type: object, instanceOf: \Sample\PersonInterface, locked: true components: - id: david, type: object, class_name: Sample\Person, injections": new: - "David Smith" - "@int: 24" - "@float: 179.2" - "@func: function($target){ return 'throws '.$target.'.'; }"
组件配置文件:PHP格式示例
<?php return [ 'compiler' => [ 'vendor_dir' => '../vendor', 'autoloaders' => [ '../sample_autoloader2.php' ], ], 'cache' => [ 'root' => '../cache', 'filename' => 'sample_di', ], 'slots' => [ [ 'id' => 'david', 'type' => 'object', 'instanceOf' => '\Sample\PersonInterface', 'locked' => true, ] ], 'components' => [ [ 'id' => 'david', 'type' => 'object', 'class_name' => 'Sample\Person', 'injections' => [ 'new' => [ "David Smith", "@int: 24", "@float: 179.2", "@func: function(\$target){ return 'throws '.\$target.'.'; }", ] ] ] ], ];
组件配置文件:参数
参数 | 必需 | 说明 | 示例 |
---|---|---|---|
compiler/vendor_dir | 是 | 指示composer供应商目录路径 | vendor_dir: "../vendor" |
compiler/autoloaders | 否 | 指示用户定义的自动加载器文件。在文件中,使用spl_autoload_register全局注册您自己的自动加载器。 | autoloaders: "../my_autoloader.php" |
cache/root | 否 | 指示缓存目录。编译器将在此目录中输出引导PHP代码。 | root: "../cache" |
cache/filename | 否 | 指示引导缓存代码的文件名基。缓存文件的完整名称将通过添加后缀'.php'来生成 | filename: "my_bootstrap" |
slots | 否 | 指示插槽数组,它附加到容器组件上以限制它。参见插槽项目参数 | - |
组件 | 是 | 指示组件数组。参见组件项目参数 | - |
组件配置文件:插槽项目参数
参数 | 说明 | 示例 |
---|---|---|
id | 指示插槽id | id: "my_service" |
type | 指示插槽的类型 | type: object |
instanceOf | 指示组件实现的类或接口 | instanceOf: MyServiceInterface |
locked | 指示插槽是否锁定。如果插槽已锁定,则无法覆盖它。 | locked: true |
组件配置文件:组件项目参数
参数 | 说明 | 示例 |
---|---|---|
id | 指示组件id | id: "my_service" |
type | 指示组件的类型 | type: object |
class | 指示组件的类 | instanceOf: MyService |
injections | 指示注入数组。参见[组件注入参数](#component_injections) | locked: true |
组件配置文件:组件注入参数
参数 | 值类型 | 说明 | 示例 |
---|---|---|---|
new | array | 指示构造函数注入。值将被传递给构造函数 | new: [ "param1", "param2" ] |
method | string | 指示方法注入。值表示方法名称。 | method: doSomething |
property | string | 指示属性注入。值表示属性名称。属性必须是公开的。 | property: tax_ratio |
params | array | 指示方法注入的参数。值必须是数组。 | params: [ "pram1", "param2" ] |
value | int string bool float null array |
指示属性注入的值。 | value: "tomato" |
许可
此库使用MIT许可。
作者
免责声明
此软件无任何保证。
我们不承担因使用此软件而引起的结果。请自行承担责任。