devanych/di-container

PSR-11 依赖注入容器的简单实现

2.1.6 2022-12-20 17:43 UTC

This package is auto-updated.

Last update: 2024-09-22 00:48:21 UTC


README

License Latest Stable Version Total Downloads GitHub Build Status GitHub Static Analysis Status Scrutinizer Code Coverage Scrutinizer Code Quality

一个简单的轻量级容器,使用自动装配实现 PSR-11 容器。

支持

  • 对象或类名。

  • 匿名函数(闭包实例)。

  • 标量(整数、浮点数、字符串、布尔值)。

  • 数组和嵌套数组,包含上述所有数据类型。

俄语详细说明指南可在此处找到。

安装

此包需要 PHP 版本 7.4 或更高版本。

composer require devanych/di-container

使用方法

创建容器

use Devanych\Di\Container;

$container = new Container();
// or with definitions array
$container = new Container($definitions);

容器中的设置

/**
 * Sets definition to the container.
 *
 * @param string $id
 * @param mixed $definition
 */
$container->set($id, $definition);

/**
 * Sets multiple definitions at once; used in the constructor.
 *
 * @param array<string, mixed> $definitions
 */
$container->setMultiple($definitions);

容器中的存在性

/**
 * Returns 'true` if the dependency with this ID was sets, otherwise `false`.
 *
 * @param string $id
 * @return bool
 */
$container->has($id);

从容器中获取

/**
 * Gets instance by definition from the container by ID.
 *
 * @param string $id
 * @return mixed
 * @throws Devanych\Di\Exception\NotFoundException If not found definition in the container.
 * @throws Devanych\Di\Exception\ContainerException If unable to create instance.
 */
$container->get($id);

/**
 * Always gets a new instance by definition from the container by ID.
 *
 * @param string $id
 * @return mixed
 * @throws Devanych\Di\Exception\NotFoundException If not found definition in the container.
 * @throws Devanych\Di\Exception\ContainerException If unable to create instance.
 */
$container->getNew($id);

/**
 * Gets original definition from the container by ID.
 *
 * @param string $id
 * @return mixed
 * @throws Devanych\Di\Exception\NotFoundException If not found definition in the container.
 */
$container->getDefinition($id);

如果定义是匿名函数或类名,则 get() 方法将仅在第一次执行函数并创建类实例,后续的 get() 调用将返回已创建的结果。

如果需要每次都执行函数并创建类实例,请使用 getNew () 方法。

如果定义是类名并且其构造函数中有依赖项,则当调用 get()getNew () 方法时,容器将在创建类实例时递归地跳过所有依赖项并尝试解决它们。

如果传递给 get()getNew() 方法的 $id 参数是类名且尚未通过 set() 方法设置,则将创建这些类的对象,就像它们已被设置一样。

如果 $id 不是类名且尚未通过 set() 方法设置,将抛出异常 Devanych\Di\Exception\NotFoundException

使用示例

简单使用

// Set string
$container->set('string', 'value');
$container->get('string'); // 'value'

// Set integer
$container->set('integer', 5);
$container->get('integer'); // 5

// Set array
$container->set('array', [1,2,3]);
$container->get('array'); // [1,2,3]

// Set nested array
$container->set('nested', [
    'scalar' => [
        'integer' => 5,
        'float' => 3.7,
        'boolean' => false,
        'string' => 'string',
    ],
    'not_scalar' => [
        'closure' => fn() => null,
        'object' => new User(),
        'array' => ['array'],
    ],
]);

// Set object
$container->set('user', fn() => new User());
$container->get('user'); // User instance
// Or
$container->set('user', User::class);
$container->get('user');
// Or
$container->set(User::class, User::class);
$container->get(User::class);
// Or without setting via `set()`
$container->get(User::class);

依赖项使用

/*
final class UserProfile
{
    private $name;
    private $age;

    public function __construct(string $name = 'John', int $age = 25)
    {
        $this->name = $name;
        $this->age = $age;
    }
}

final class User
{
    private $profile;

    public function __construct(UserProfile $profile)
    {
        $this->profile = $profile;
    }
}
*/

$container->set('user_name', 'Alexander');
$container->set('user_age', 40);

$container->set('user', function (\Psr\Container\ContainerInterface $container): User {
    $name = $container->get('user_name');
    $age = $container->get('user_age');
    $profile = new UserProfile($name, $age);
    return new User($profile);
});

$container->get('user');

// Or

$container->set(UserProfile::class, function (\Psr\Container\ContainerInterface $container): UserProfile {
    return new UserProfile($container->get('user_name'), $container->get('user_age'));
});

$container->get(User::class);

// Or with default values (`John` and `25`)

$container->get(User::class);

使用依赖项和工厂

/*
final class UserProfileFactory implements \Devanych\Di\FactoryInterface
{
    public function create(\Psr\Container\ContainerInterface $container): UserProfile
    {
        return new UserProfile($container->get('user_name'), $container->get('user_age'));
    }
}
*/

$container->setMultiple([
    UserProfile::class => UserProfileFactory::class,
    // Or without autowiring
    // UserProfile::class => fn => UserProfileFactory(),
    // UserProfile::class => new UserProfileFactory(),
    'user_name' => 'Alexander',
    'user_age' => 40,
]);

$container->get(User::class); // User instance
$container->get(UserProfile::class); // UserProfile instance