atanvarno / dependency
PSR-11 依赖注入容器
Requires
- php: ^7.0
- psr/container: ^1.0.0
- psr/simple-cache: ^1.0.0
Requires (Dev)
- atanvarno/test-util: ^0.1.0
- phpunit/phpunit: ^6.1.3
Provides
- psr/container-implementation: 1.0.0
README
一个基本的 PSR-11 依赖注入容器,实现了 ArrayAccess
。
特性
Atanvarno\Dependency
并不通过反射提供自动装配。它仅是一个基础的容器。
要求
PHP >= 8.0 是必须的,但推荐使用 PHP 的最新稳定版本。
安装
Atanvarno\Dependency 可在 Packagist 上找到,并可以使用 Composer 进行安装
$ composer require atanvarno/dependency
基本用法
<?php use Atanvarno\Dependency\Container; use function Atanvarno\Dependency\{entry, factory, object, value}; $container = new Container(); // Add a value to the container $container['value ID'] = 'your value'; // Add a lazy loaded class to the container $container['class ID'] = object(YourClass::class, ['argument1', entry('value ID')]); // Get a value from the container $value = $container['value ID']; var_dump($value === 'your value'); // true // Get a class instance from the container $instance = $container['class ID']; var_dump($instance instanceof YourClass::class); // true
用法
获取条目
有两种方法可以获取条目
// Using array syntax $item1 = $container['ID']; // Calling get() $item2 = $container->get('ID');
从 ID 获取的条目默认情况下将是相同的实例
var_dump($item1 === $item2); // true
您可以在定义条目时指定,每次获取特定 ID 时它都将是一个新实例(参见 延迟加载条目)。
检查条目
有两种方法可以检查条目是否可用,每个都返回 bool
// Using array syntax isset($container['ID']); // Calling has() $container->has('ID');
删除条目
有两种方法可以删除条目
// Using array syntax unset($container['ID']); // Calling delete() $container->delete('ID');
添加条目
有几种方法可以添加条目
// Using array syntax $container['ID'] = $entry; // Calling set() $container->set('ID', $entry);
$entry
可以是任何 PHP 值。当以这种方式使用时,Atanvarno\Dependency\Container
是一个简单的键值存储,与数组没有太大区别。
条目也可以定义为延迟加载。
条目也可以通过构造函数添加(参见 实例化)。
延迟加载条目
任何条目都可以定义为 延迟加载,因此它仅在访问时构建。
包含两个辅助函数,允许您定义延迟加载的条目: factory()
和 object()
。
(示例使用的是 set()
方法,但数组语法也可以使用。)
您可以使用 factory()
从任何 callable
返回值
$container->set('ID', factory( function() { // ... } ));
您可以使用 object()
从其类名返回对象
$container->set('ID', object(ClassName::class));
factory()
和 object()
都接受一个数组作为参数,将传递给 callable
或构造函数。这些参数可以是任何 PHP 值,也可以是其他容器条目。其他容器条目可以通过使用 entry()
函数引用
// Setting a factory $callable = function(int $arg1, ClassName $arg2) { // ... }; $container->set('ID', factory($callable, [5, entry('ClassInstance')])); // Setting an object class ClassName { public function __construct(int arg1, OtherClass $arg2) { // ... } } $container->set('ID', object(ClassName::class, [5, entry('OtherInstance')]));
(容器本身可以使用默认条目 ID container
进行引用。如果您需要容器具有不同的条目 ID,请使用 setSelfId()
。)
函数factory()
和object()
都接受一个可选的第三个bool
参数,用于确定它们返回的第一个值是否应该被注册,并在检索条目时始终返回(默认行为),或者每次都返回一个新的值(传入false
)。
// A non-registered factory $container->get('ID', factory(function(){/*...*/}, [], false)); // A non-registered object $container->get('ID', object(ClassName::class, [], false));
设置属性和调用方法
您可能想要设置新创建对象的public
属性或调用其方法,以便对其进行配置以供使用。
函数factory()
和object()
都返回一个Definition
,它提供了具有流畅接口的方法,允许您这样做。
$container->set( 'ID', object(ClassName::class, [$param1, entry('param2')]) ->method('methodName', [$param3, entry('param4')]) // Call a method with parameters ->property('propertyName', 'value') // Then set a property value ->property('otherProperty', entry('aValue')) // Then set another property );
示例使用object()
,但也可以与factory()
一起使用。注意,如果factory()
没有定义对象实例,这些方法将不起作用。
委托查找功能
Atanvarno\Dependency\Container
实现了container-interop
的委托查找功能,并可以作为父容器/组合/委托和子容器使用。
要添加子容器(并将$container
变为组合容器)使用addChild()
。
$container->addChild($otherContainerA);
后续调用将添加更多的子容器。
要添加父容器(并将$container
的依赖项查找委托出去)使用setDelegate()
。
$container->setDelegate($otherContainerB);
后续调用将替换父容器。
流畅接口
Atanvarno\Dependency\Container
提供了一个流畅接口,允许链式调用多个方法。这些方法每个都返回Container
实例。
addChild()
clearCache()
delete()
get()
set()
setDelegate()
setSelfId()
实例化
当容器被实例化时,它可选地接受一个Definition
实例的数组(由factory()
、object()
和value()
返回),这些实例将被添加到容器中。此数组按条目ID索引。
$container = new Container([ 'called' => factory( function(ContainerInterface $c){return $c->get('value');}, [entry('container')] ), 'object' => object( ClassName::class, [entry('value'), true] ) ->property('name', entry('called') ->method('methodName', 500), 'value' => value('an arbitary PHP value'), ]);
您可以创建一个配置文件来返回此数组。
<?php // containerConfig.php use function Atanvarno\Dependency\{entry, factory, object, value}; return [ 'app' => object( AppClass::class, [ entry('container'), entry('router'), entry('cache'), entry('logger') ], false ), 'cache' => object(CacheClass::class, [entry('cache config')]), 'cache config' => factory( function(string $configDir){return $configDir . '/cache.php';}, [entry('config directory')] ), 'config directory' => value(__DIR__), 'logger' => object(LoggerClass::class, [entry('log config')]) ->method('pushHandler', [entry('log handler'), Logger::WARNING]), 'log config' => factory( function(string $configDir){return $configDir . '/logger.php';}, [entry('config directory')] ), 'log handler' => object(LogHandler::class, [entry('log path')]), 'response' => factory( function(AppClass $app) { return $app->getResponse($app->getRequest()); }, [entry('app')] ), 'router' => object(RouterClass::class, [entry('router config')]), 'router config' => factory( function(string $configDir){return $configDir . '/routes.php';}, [entry('config directory')] ), ];
然后将其包含在构造函数调用中。
$container = new Container(include '../config/containerConfig.php');
缓存
Atanvarno\Dependency\Container
可以使用PSR-16缓存来持久化已注册项。注意,它不持久化定义;仅持久化至少返回过一次的已注册值。
缓存对用户不可见;调用delete()
、get()
和set()
将根据需要使用和更新缓存。
如果您想要清除容器的缓存,请使用clearCache()
。
// Clears the container's cache; other values stored in the cache are untouched $container->clearCache();
构造函数接受缓存作为其第二个参数,以及用作缓存的可选键的第三个参数(默认为container
)。
/** @var CacheInterface $cache PSR-16 cache. */ $cache = /* ... */ ; $container = new Container([], $cache, 'container-cache-key');
构造函数还接受一个entry()
,它指向第一个参数中定义的缓存,因此缓存实例可以由容器本身加载。
$container = new Container( ['cache' => object(CacheClass::class)], entry('cache'), 'cache-key' );
异常
所有抛出的异常都实现了PSR-11的ContainerExceptionInterface
。
完整API
请参阅API。