mmoreram / doppo
小型依赖注入容器
Requires
- php: >=5.3.7
- psr/log: *
This package is auto-updated.
Last update: 2024-08-29 04:19:48 UTC
README
哦,不……另一个用PHP编写的依赖注入容器?
事实上是的,但这个项目的目的是学术性的,旨在讨论关于构建依赖注入容器最佳方法的一些有趣话题。
Doppo是一个基本的DIC实现,实现了一些功能(没有新功能,只是我认为最重要的和有用的),使用TDD开发,经过几次重构和几次架构变更。
那么,它究竟是什么呢?让我们看看它的功能。
容器
Doppo容器需要用两个必需的参数来构建。首先,我们需要定义我们想要编译的配置,其次,我们需要定义调试标志。
use Doppo\Doppo; $configuration = []; $debug = true; $doppo = new Doppo( $configuration, $debug );
这是一个空的Doppo容器,我们可以看到配置是空的,并且是在调试模式下创建的。这些信息不能再修改,所以它就像容器实例的指纹。
We could not define this object as immutable because when is compiled, the
object's state changes from an external point of view.
这个$configuration
值定义了容器应该如何编译以及所有定义的服务应该如何构建。让我们看看完整的定义。
定义
$configuration = array( 'my_service' => array( 'class' => 'My\Class\Namespace', 'arguments' => array( '@my_other_service', '~my_parameter', 'simple_value', ) ), 'my_other_service' => array( 'class' => 'My\Class\Namespace', ), 'my_parameter' => 'parameter_value', );
配置允许两种类型的元素:服务和参数。从DIC的角度来看,它们之间的区别在于任何服务定义都必须包含一个类值,所以如果定义是一个数组,并且存在class
键,这将被视为一个服务。
否则,将视为一个参数。
正如你所看到的,当我们定义服务的参数时,我们可以使用前缀@
引用另一个服务,我们也可以使用前缀~
引用参数值,或者我们可以直接传递一个原始值,如字符串、数组或对象。
将依赖项传递给服务的方式只能是构造函数。一些其他容器允许您使用setter或公共变量来构建服务,但这个不行。考虑到服务依赖项必须在构造函数中注入,否则它不是依赖项而是配置,容器应该只了解构建,而不是配置,至少在特定实现之前是这样。
编译
一旦容器用配置和调试模式构建,我们必须编译它。在这种情况下,容器将内部构建一个结构来正确地提供服务实例和参数值。
use Doppo\Doppo; $configuration = array( 'my_service' => array( 'class' => 'My\Class\Namespace', 'arguments' => array( '@my_other_service', '~my_parameter', 'simple_value', ) ), 'my_other_service' => array( 'class' => 'My\Class\Namespace', ), 'my_parameter' => 'parameter_value', ); $debug = true; $doppo = new Doppo( $configuration, $debug ); $doppo->compile();
容器编译只能进行一次。如果我们编译了一个已编译的容器,将抛出异常。
用法
一旦容器编译完成,您可以使用get
方法检索任何定义的服务实例,使用getParameter
方法检索任何定义的参数值。
$myServiceInstance = $doppo->get('my_service'); $myParameterValue = $doppo->getParameter('my_parameter');
当您检索服务实例时,它只构建一次。这意味着在内部,当任何服务被请求并构建时,在返回之前,结果实例将存储在本地。当服务再次被调用时,现有的实例将被返回而不是再次构建它。
缓存
这里的问题是,容器在每次需要时都会被构建和编译。这意味着在每次执行时都会处理和检查容器,这使得它非常低效。
此包还提供了一个主类Doppo的扩展。它被称为CacheableDoppo,构建方式如下。
use Doppo\Doppo; $configuration = []; $debug = true; $cachePath = '/tmp/doppo.cache.php'; $doppo = new Doppo( $configuration, $debug, $cachePath );
这个新类与之前的类工作方式相同,都实现了相同的接口ContainerInterface
,但这个类在第一个之上增加了一个缓存层。当容器被编译时,会生成一个缓存文件,并将其存储在指定的位置,这是最后一个构造函数参数指定的。
每次容器需要构建时,如果缓存文件已经创建,则会加载这个文件,并提供一组定义所有服务构建规范的方法。
装饰器
容器也可以被装饰。装饰器类也必须实现ContainerInterface
,并且可以在不改变旧实现的情况下,向指定的接口添加一些行为。
LoggableDecorator
这个装饰器根据容器的调试模式记录所有与公共容器API的外部交互。
use Doppo\Doppo; $configuration = []; $debug = true; $cachePath = '/tmp/doppo.cache.php'; $logger = new Logger(); $doppo = new LoggableDecorator( new Doppo( $configuration, $debug, $cachePath ), $logger );
Logger实例必须实现由包Psr\Log
提供的Psr\Log\LoggerInterface
。您可以在这些包列表中看到一些公共实现。