gravatalonga / container
PSR-11 容器实现,轻量且强大。具有懒加载工厂、工厂、可选的服务共享、数组访问等功能,非常灵活。
Requires
- php: ^8.0|^8.1
- psr/container: ^2.0
Requires (Dev)
- infection/infection: ^0.18.0
- phpunit/phpunit: ^9
- rector/rector: ^0.13.4
- scrutinizer/ocular: ^1.9
- vimeo/psalm: ^4.3.0
Provides
README
容器
遵循PSR-11的容器实现。
要求
安装
composer require gravatalonga/container
使用方法
基本使用
use Gravatalonga\Container\Container; $container = new Container(); $container->set('random', function() { return rand(0, 1000); }); $container->share('uniqueSeed', function() { return rand(0, 1000); }); // create alias 'sessionId' $container->alias('uniqueSeed', 'sessionId'); echo $container->get('random'); // get random number each time you call this. if ($container->has('uniqueSeed')) { echo $container->get('uniqueSeed'); // get same random number. }
当创建容器的新实例时,您可以传递第一个参数配置或已绑定到容器的条目。
use Gravatalonga\Container\Container; new Container([ 'settings' => ['my-settings'], FooBar::class => function (\Psr\Container\ContainerInterface $c) { return new FooBar(); } ]);
使用服务提供者
use Gravatalonga\Container\Container; $container = new Container(); $container->set(RedisClass::class, function () { return new RedisClass(); }); // then you can use... $cache = $container->get('Cache');
当使用 set
、factory
或 share
与闭包,并且您想获取 Container
本身时,您可以将 ContainerInterface
的类型提示作为参数传递。
use Gravatalonga\Container\Container; use Psr\Container\ContainerInterface; $container = new Container([ 'server' => 'localhost', 'username' => 'root' ]); $container->set('Cache', function (ContainerInterface $container) { // some where you have binding this RedisClass into container... return $container->make(RedisClass::class, [ 'server' => $container->get('server'), 'username' => $container->get('username') ]); }); // set is a method alias of factory $container->factory('CacheManager', function() { return new CacheManager(); }); // then you can use... $cache = $container->get('Cache');
使用数组样式的访问
use Gravatalonga\Container\Container; $container = new Container(); $container[FooBar::class] = function(ContainerInterface $container) { return new FooBar($container->get('settings')); }; if (isset($container[FooBar::class])) { echo $container[FooBar::class]->helloWorld(); }
别名
别名类似于显示的名称,它可以使得从一条条目到另一条条目的别名成为可能。如果找不到,它将抛出异常。
use Gravatalonga\Container\Container; $container = new Container(); $container->set('settings', ['driver' => 'default']); $container->set(FooBar::class, function($settings) { return new FooBar($settings); }); $container->alias(FooBar::class, 'foo.bar'); $foobar = $container->get('foo.bar');
可调用作为替代
use Gravatalonga\Container\Container; $class = new class { public function get(): int { return mt_rand(0, 100); } }; $container = new Container(); $container->factory('random', [$class, 'get']); $foobar = $container->get('random'); // it will get random int
扩展
为了使实现更易于其他服务提供者,创建了 extend
方法。
use Gravatalonga\Container\Container; class Test { /** * @var string */ public $name; public function __construct($name = 'Jonathan Fontes') { $this->name = $name; } } $container = new Container(); $container->get(Test::class, function(ContainerInterface $container) { return new Test; }); $container->extend(Test::class, function(ContainerInterface $container, $test) { return new Test($test->name.' - The greatest!'); }); echo $container->get(Test::class); // It will print 'Jonathan Fontes - The greatest!';
高级使用
容器能够解析未绑定的类,它将从已绑定的 __construct
类型提示/内置中解析依赖关系。请阅读下面的示例代码。
信息:内置是在PHP中构建的类型,如
string
、int
、boolean
等。类型提示是由用户创建的类型,例如,当创建一个类时,您正在创建一个新类型。
使用类型提示类
use Gravatalonga\Container\Container; class FooBar {} class Test { public function __construct(FooBar $foobar) { $this->foobar = $foobar; } } $container = new Container(); $container->set(FooBar::class, function () { return new FooBar(); }); $container->get(Test::class); // FooBar it will inject into Test class.
注意:我们仅在它们绑定到容器中时支持在构造时解析自动绑定参数。否则,如果找不到条目,将抛出异常。
使用内置类型
use Gravatalonga\Container\Container; class Test { public function __construct(string $name) { $this->name = $name; } } $container = new Container(); $container->set('name', 'my-var'); $container->get(Test::class); // my-var it will inject into Test class.
如果参数接受可为空,如果无法解析它,则将传递默认值,在这种情况下是 null
。
use Gravatalonga\Container\Container; class Test { /** * @var string */ private $name; public function __construct(string $name = null) { $this->name = $name; } } $container = new Container(); $container->get(Test::class); // null it will inject into Test class.
它还将尝试通过其默认值解析构造的自动绑定,它将检查 __construct
的默认值,并将传递该默认值。
第一种情况,如果值是简单的内置类型值。
use Gravatalonga\Container\Container; class Test { /** * @var string */ private $name; public function __construct($name = 'Jonathan Fontes') { $this->name = $name; } } $container = new Container(); $container->get(Test::class); // 'Jonathan Fontes' it will pass into container...
提示
众所周知,使用单例模式是一个反模式。但小的特性不会伤害你
因此,您可以使用
$container = new Container();
// ...
Container::setInstance($container);
然后您可以得到容器的实例,
$container = Container::getInstance();
提示:容器可以检测循环依赖。
变更日志
请参阅变更日志了解最近的变化。
测试
composer grumphp
贡献
请参阅CONTRIBUTING 和 行为准则以获取详细信息。
安全性
如果您发现任何安全相关的问题,请通过jonathan.alexey16[at]gmail.com发送电子邮件,而不是使用问题跟踪器。
致谢
许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证文件。