Peroxide 容器,一个简单的工厂驱动的 PSR-11 依赖注入容器,无依赖和低功能。

v1.2.1 2024-04-11 21:52 UTC

This package is not auto-updated.

Last update: 2024-09-27 00:30:45 UTC


README

eng / pt-br

Peroxide/容器

一个简单的依赖注入容器,设计用于与 API 一起使用,遵循 PSR-11 标准。它具有最小的功能,并且独立运行,无外部依赖。

我们的理念

我们热衷于与尽可能干净和简单的组件一起工作。 Peroxide\Container 是从类似 Laminas\ServiceManagerPimplePHP-DI 的库中汲取灵感而融合而成的。

我们的巨大优势是没有任何外部依赖。所有配置都通过 PHP 代码使用数组配置文件来实现。你只需要确保你的框架支持 PSR-11,设置配置,然后你就可以开始你的编码之旅了。

如何使用它

安装

composer require peroxide/container

开始你的旅程

Peroxide\Container 完全符合 PSR-11 标准,并提供以下方法

# From PSR-11
public function get(string $id): object;
public function has(string $id): bool;

# From our interface SetDependency
public function set(string $id, callable $factory): void;
public function setInvokableClass(string $id, string $invocableClass): void;

将你的配置作为 数组 创建

<?php
use Peroxide\DependencyInjection\Container;

$config = [
    YourDependencyName::class => fn() => new YourDependencyName(),
    YourDependency::class     => YourDependencyFactoryClass::class,
    
    // should be invokable class
    ConcreteClass::class      => new ConcreteClassFactory(),
    
    // Or passing as reference string
    ConcreteClass::class      => ConcreteClassFactory::class
];

$container = new Container($config);

// how to get dependencies
$container->get(YourDependencyName::class);
$container->get(YourDependency::class);
$container->get(ConcreteClass::class);

创建你的工厂类

use Psr\Container\ContainerInterface;
use Peroxide\DependencyInjection\Interfaces\ContainerFactory;

class ConcreteClassFactory implements ContainerFactory
{
    public function __invoke(ContainerInterface $container): ConcreteClass
    {
        // config your dependency injection here
        // you can compose your dependency
        // return new ParentDependency($container->get(DependencyChild::class));
        return new ConcreteClass();
    }
}

在获取容器实例后,也可以单独设置依赖项

use Peroxide\DependencyInjection\Container;

$container = new Container();

$container->set(DependencyPath::class, fn() => new DependencyInstance());

如果依赖项不存在,则将其创建;如果存在,则由新的工厂替换。

更多配置

要处理容器内的依赖注入,你可以轻松使用 箭头函数 来组合你的依赖项。

$container = new Container([
    // Dependency parent with dependency child
    
    // all dependencies should be involved by a Closure(function() or fn()) 
    Dependency::class              => fn() => new Dependency(),
    
    ComponentThatHasAnotherDependency::class => function($container) { 
        return new ComponentThatHasAnotherDependency(
            $container->get(Dependency::class)
        );
    },

    // or simply
    ComponentThatHasAnotherDependency::class => fn($c) => new ComponentThatHasAnotherDependency($c->get(Dependency::class)),

    // more complex injections
    ComponentThatHasTwoDeps::class => fn($c) => new ComponentThatHasTwoDeps(
        $c->get(Dependency::class),
        $c->get(AnotherDependency::class),
    )
]);

你还可以使用扩展运算符来组合配置,如示例所示

use Peroxide\DependencyInjection\Container;
# on 'dependencies.php' config file
$config1 = [ ... ];
$config2 = [ ... ];
return [...$config1, ...$config2];

// -------------------

$config = require __DIR__ . '/dependencies.php';

$container = new Container($config);

如何处理单例?

只需使用 Singleton 可调用类,以下是一个示例

use Peroxide\DependencyInjection\Container;
use Peroxide\DependencyInjection\Invokables\Singleton;

$container = new Container([
    // Dependency parent with dependency child
    Dependency::class       => new Singleton(fn() => new Dependency()),
    
    ParentDependency::class => new Singleton(
        fn($container) => new ParentDependency($container->get(Dependency::class))
    ),
    
    // Singleton passing factory as reference string
    ConcreteClass::class    => new Singleton(ConcreteClassFactory::class)
]);

Peroxide\DependencyInjection\Invokables\Singleton 类作为包装器,用于指示我们的容器我们不希望每次检索时都创建此类的新实例。

Singleton 构造函数的第一个参数,只接受可调用类或闭包。

为什么我不能在容器上配置参数?

我们认为在依赖容器中存储配置值是不必要的。相反,每个服务都应该使用外部环境数据来配置。这样做可以将你项目的配置集中化。