🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
目录 [TOC] WorkerA 提供了一个简单好用的 IOC 容器 WorkerF\IOCContainer。 IOC 容器是一个特殊的工厂类,它可以帮助你获取你需要的对象,并自动帮你注入需要的依赖 (包括依赖的依赖注入,一直到没有依赖为止)。 IOC 容器提供了单例操作、获取实例、执行实例方法 (给方法注入依赖) 等功能,你可以使用 IOC 容器解决多重依赖的问题,提高开发的效率。 ## 单例 设置单例: singleton 方法 ```php use WorkerF\IOCContainer; ... $a = new A(); IOCContainer::singleton($a); ``` 获取单例: getSingleton 方法 ```php // 传入要获取单例的类名 $a = IOCContainer::getSingleton('A'); ``` 设置单例时还可以指定名称: ```php $a = new A(); // 设置单例,指定名称 IOCContainer::singleton($a, 'my_singleton'); // 获取单例 $a = IOCContainer::getSingleton('my_singleton'); ``` 销毁单例:unsetSingleton 方法 ```php // 销毁类 A 的单例 IOCContainer::unsetSingleton('A'); // 再次获取为 null IOCContainer::getSingleton('A'); ``` ## 单例注册 IOCContainer 提供了一个 register 方法用来注册单例。和 singleton 方法不同的是,register 方法可以实现自定义类替换抽象类的功能。 这么说可能会难以理解,那么举例说明一下: ```php // set exception handler IOCContainer::register( WorkerF\Exceptions\ExceptionHandler::class, App\Exceptions\Handler::class ); ``` 上述是 bootstrap/boot.php 中设置异常 Handler 的代码。WorkerF\Exceptions\ExceptionHandler::class 在这里算是一个抽象类,是所有异常 Handler 的模板,App\Exceptions\Handler::class 是实际传入的类。即框架获取单例实例时会根据 WorkerF\Exceptions\ExceptionHandler::class 获取,但实际上获取到的是 App\Exceptions\Handler::class 的实例。 这样一来,可以更换自定义 Handler 而又不用改变框架底层代码。 register 方法不传第二个参数时,和 singleton 没有什么区别,只不过 singleton 的参数是实例,register 的参数是类名。 ```php // 只使用默认 ExceptionHandler IOCContainer::register(WorkerF\Exceptions\ExceptionHandler::class); ``` ## 获取实例 IOCContainer 提供了 getInstance 方法来获取一个实例,由 getInstance 方法获取的实例会自动进行依赖注入。 如果注入的实例也有依赖的话,IOC 容器会继续向下查找依赖进行依赖注入,直到所有的依赖注入完成。 例如: ```php class Foo { public $a = 1; public $b = 2; } class Foz { public $a = 5; public $b = 6; public function __construct(Foo $foo) { $this->a = $foo->a + $this->a; $this->b = $foo->b + $this->b; } } class Bar { public $a = 0; public $b = 0; public function __construct(Foz $foz) { $this->a = $foz->a; $this->b = $foz->b; } } // 获取 Bar 的实例,IOCContainer 会自动进行依赖注入 $bar = IOCContainer::getInstance(Bar::class); var_dump($bar->a); // 6 var_dump($bar->b); // 8 ``` > 注:1.1.0 版本中 IOCContainer 存在只能注入一层的问题,请升级到 1.1.1 ( 查看 [旧版本升级-小版本升级](旧版本升级.md))。 IOCContainer 还提供了获取实例单例的版本 getInstanceWithSingleton,如果要获取的实例没有设置单例,getInstanceWithSingleton 方法会将该实例设置为单例并返回该实例。 ## 方法运行 IOCContainer 的 run 方法用来运行一个实例的方法,并且如果该方法有依赖则进行依赖注入。WorkerA 的路由分发执行控制器方法时就是用的 run 方法。 例子: ```php class Foo { public $a = 1; public $b = 2; } class Bar { public function f1(Foo $foo) { return $foo->a + $foo->b; } } $result = IOCContainer::run(Bar::class, 'f1'); // result is 3 ``` 你还可以使用 run 方法的第三个参数给要运行的方法传入额外参数: ```php class Foo { public $a = 1; public $b = 2; } class Bar { // 注意额外传入的参数应该在要注入的参数之后 public function f1(Foo $foo, $c, $d) { return $foo->a + $foo->b + $c + $d; } } $result = IOCContainer::run(Bar::class, 'f1', [4, 2]); // result is 9 ```