gravatalonga/container

PSR-11 容器实现,轻量且强大。具有懒加载工厂、工厂、可选的服务共享、数组访问等功能,非常灵活。

1.8.4 2022-06-07 08:00 UTC

README

Container

容器

Latest Version on Packagist Software License Total Downloads Coverage Status Quality Score Type coverage PHP Unit Say Thanks

遵循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');

当使用 setfactoryshare 与闭包,并且您想获取 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中构建的类型,如stringintboolean等。类型提示是由用户创建的类型,例如,当创建一个类时,您正在创建一个新类型。

使用类型提示类

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)。有关更多信息,请参阅许可证文件