dmt-software/di-plug

PHP 依赖容器抽象

v0.3.0 2023-03-28 06:24 UTC

This package is auto-updated.

Last update: 2024-08-28 09:40:37 UTC


README

介绍

psr-11 引入了一种标准化的方法,允许包、库和框架从容器中检索对象。此包还允许通过统一的接口添加依赖,而无需使用特定的容器实现。这有助于开发者更容易地访问依赖注入容器以安装其包。

安装

composer require dmt-software/di-plug

使用方法

手动创建容器

use DMT\DependencyInjection\Adapters\PimpleAdapter;
use DMT\DependencyInjection\Container;
use Pimple\Container as PimpleContainer;
 
$container = new Container(new PimpleAdapter(new PimpleContainer()));
$container->set(SomeClass::class, fn() => new SomeClass($container->get(SomeDependency::class)));

自动检测

使用容器构建器将您的容器实例包装在 DMT\DependencyInjection\Container 中。

use DMT\DependencyInjection\ContainerFactory;
 
/** @var object $supportedContainerInstance */
$factory = new ContainerFactory();
$container = $factory->createContainer($supportedContainerInstance);
$container->set(SomeClass::class, fn() => new SomeClass($container->get(SomeDependency::class)));

自动发现

注意:当另一个依赖项使用受支持的容器时,自动发现可能使用与预期不同的容器。

代码可以发现已安装的依赖容器。

use DMT\DependencyInjection\ContainerFactory;
 
$factory = new ContainerFactory();
$container = $factory->createContainer();
$container->set(SomeClass::class, fn() => new SomeClass($container->get(SomeDependency::class)));

概念

未注册的实例

如果使用不在容器中的 className 调用 Container::get(),将为该类创建一个新实例。这也适用于带有构造函数参数的调用。

注意:当容器创建新实例时,它将不会被设置在容器中。即使使用相同的构造函数参数调用也不会。

自动注入容器

除了注入所有依赖项之外,可以选择只注入容器并在需要时解决依赖项。这可以通过使用 HasContainer 特性轻松实现。

use DMT\DependencyInjection\Container;
use DMT\DependencyInjection\Traits\HasContainer;

class SomeClass
{
    use HasContainer;
    
    public function doSomething(): void
    {
        $dependency = $this->getContainer()->get(SomeDependency::class);
        $dependency->doSomething();
    }
}

即使 HasContainer 在另一个特性中使用,但仅限于一层。例如,使用下面的特性可以使 getTwigEngine() 调用检索父类中的模板引擎。

use DMT\DependencyInjection\Traits\HasContainer;
use Twig\Environment;

trait HasTwigEngine
{
    use HasContainer;
    
    public function getTwigEngine(): Environment
    {
        return $this->getContainer()->get(Environment::class);
    }
}

服务提供者

可以使用服务提供者在容器中注册或更改依赖项。

use DMT\DependencyInjection\Container;
use DMT\DependencyInjection\ServiceProviderInterface;
use Twig\Environment;
use Twig\Extension\StringLoaderExtension;

class MyServiceProvider implements ServiceProviderInterface
{
    /**
     * Register dependencies and ensure twig is enabled with string loader extension.   
     */
    public function register(Container $container): void
    {
        if (!$container->has(Environment::class)) {
            $container->set(Environment::class, fn() => new Environment());
        }
        
        $env = $container->get(Environment::class);
        if (!$env->hasExtention(StringLoaderExtension::class)) {
            $env->addExtension(new StringLoaderExtension());
        }

        $container->set(MyClassInterface::class, fn() => new MyClass($container->get(Environment::class)));
    }
}

支持