rkr / php-ioc-contract
0.1.1
2022-09-30 07:24 UTC
Requires
- php: >= 5.3
Suggests
- rkr/php-di-ioc-adapter: An adapter for PHP-DI
README
IOC 容器合约
只要不是 1.0 版本,请不要使用这个库。
摘要
本项目提供了 API 和三个不同关注点的行为文档
- InstanceContainer - 一个返回与键关联的实例的容器。
- ObjectFactory - 一个抽象工厂,用于从现有实例创建新对象实例。例如,用于工厂创建新实体。
- MethodInvoker - 调用一个方法、函数或闭包。例如,用于调度器启动子程序。
动机
假设你想构建一个基于规则的服务调度器(或类似于 silex 的 HTTP 路由器),只有满足一定条件时才调用注册的闭包
$serviceDispatcher = new ServiceDispatcher(); $serviceDispatcher->register('service-name', 3600 /* timeout sek. */, function () { /* do something every hour */ }); $serviceDispatcher->run();
如果我已经有了需要工作的域对象,那就很有趣了。这看起来是这样的
$serviceDispatcher = new ServiceDispatcher(); $serviceDispatcher->register('service-name', 3600 /* timeout sek. */, function (BusinessObject $businessObject) { /* do something every hour */ $businessObject->doSomething(); }); $serviceDispatcher->run();
$serviceDispatcher 不应直接了解 BusinessObject。但 ServiceDispatcher 可能知道一个通用的方法来调用一个可调用对象(如闭包),并通过 ServiceDispatcher 范围外的组件解析这些参数。这是如何实现的不是 ServiceDispatcher 的关注点。它只是以某种方式发生。
可以通过依赖注入容器实现这个目标。现在有不同接口的 ioc 容器 (我现在的最爱是 PHP-DI)。因此,我们需要一个公共接口来传递一个实例,该实例知道如何实例化我们的域对象,这样我们就可以直接使用它们。
$container = new Container(require 'config/di-cfg.php'); $serviceDispatcher = new ServiceDispatcher($container); $serviceDispatcher->register('service-name', 3600 /* timeout sek. */, function (BusinessObject $businessObject) { /* do something every hour */ $businessObject->doSomething(); }); $serviceDispatcher->run();
现在 ServiceDispatcher 实现中的 run 方法可以简单地看起来像这样
use Ioc\MethodInvoker; class ServiceDispatcher { /** @var MethodInvoker */ private $methodInvoker; /* ... */ /** @param MethodInvoker $methodInvoker */ public function __construct(MethodInvoker $methodInvoker) { $this->methodInvoker = $methodInvoker; } /* ... */ public function run() { foreach($this->registry as $serviceName => $service) { if($service['lockUntil'] > time()) { continue; } try { $this->methodInvoker->invoke($service['fn'], array('serviceName' => $serviceName)); } finally { $service['lockUntil'] = time() + $service['timeout']; } } } }
InstanceContainer
InstanceContainer 主要在 DI 容器中用于只有一个对象实例应该被使用时。这略不同于单例模式,因为你可以有多个具有不同配置的 DI 容器,它们可能会注入提供接口的不同实现。对于实现细节,请参阅 phpdoc-blocks。
ObjectFactory
ObjectFactory 主要在通用工厂中用于创建实体。对于实现细节,请参阅 phpdoc-blocks。
MethodInvoker
调用一个可调用对象方法、函数或闭包,并自动解析所需参数(如果尚未提供)。对于实现细节,请参阅 phpdoc-blocks。