assodepicche/php-di-container

PHP 依赖注入容器

dev-main 2023-11-30 03:14 UTC

This package is auto-updated.

Last update: 2024-09-30 01:57:35 UTC


README

根据 DotNetTricks,DI 容器是一个创建依赖项并在需要时自动注入它们的框架。它根据请求自动创建对象并在需要时注入它们。DI 容器以简单和便捷的方式帮助我们管理应用程序中的依赖项。

DI 容器创建定义的类的对象,并将所有必需的依赖项作为对象注入,包括构造函数、属性或方法,这些方法在运行时触发并在适当的时间销毁自己。这个过程完成,这样我们就不必总是手动创建和管理对象。

此存储库包含用于 PHP 项目的 DI 容器。

目录

  1. 接口

  2. 实现

  3. 安装

  4. 入门

  5. 贡献

  6. 联系

接口

DependencyInjectionContainer 接口定义了四个方法:autowiregetsetsingleton。所有这些方法都期望一个类或接口名称作为字符串,但只有后两个方法还期望一个 callable,它代表类或接口的定义。

<?php

declare(strict_types=1);

namespace Container\Adapter;

interface DependencyInjectionContainer
{
    public function autowire(string $className): object;

    /**
     * @template TClassName
     * @param class-string<TClassName> $className
     * @return TClassName
     */
    public function get(string $className): object;

    public function has(string $className): bool;

    public function set(string $className, callable $definition): self;

    public function singleton(string $className, callable $definition): self;
}

实现

"DependencyInjectionContainer" 接口的实现是 "DependencyContainer" 类,并使用 PHP 反射 API 来管理已注册类的实例化。

<?php

declare(strict_types=1);

namespace Container\Infrastructure;

use Container\Adapter\DependencyInjectionContainer;
use ReflectionClass;
use ReflectionParameter;

final class DependencyContainer implements DependencyInjectionContainer
{
    private array $definitions = [];

    private array $singletons = [];

    public function autowire(string $className): object
    {
        $reflectionClass = new ReflectionClass($className);

        $constructorParameters = array_map(
            fn (ReflectionParameter $parameter) => $this->get($parameter->getType()->getName()),
            $reflectionClass->getConstructor()?->getParameters() ?? []
        );

        return new $className(...$constructorParameters);
    }

    public function get(string $className): object
    {
        if ($instance = $this->singletons[$className] ?? null) {
            return $instance;
        }

        $definition = $this->definitions[$className] ?? $this->autowire(...);

        return $definition($className);
    }

    public function has(string $className): bool
    {
        return isset($this->definitions[$className]) || isset($this->singletons[$className]);
    }

    public function set(string $className, callable $definition): self
    {
        $this->definitions[$className] = $definition;

        return $this;
    }

    public function singleton(string $className, callable $definition): self
    {
        $this->definitions[$className] = function () use ($className, $definition) {
            $this->singletons[$className] = $definition($this);

            return $this->singletons[$className];
        };

        return $this;
    }
}

安装

首先,请确保您已安装 PHP(8.2 版本或更高版本),然后克隆此存储库或通过 composer 安装库。

  • 通过 Git 安装
git clone git@github.com:AssoDePicche/php-di-container.git
  • 通过 Composer 安装
composer require assodepicche/php-di-container

入门

实例化 DependencyContainer

<?php

use Container\Infrastructure\DependencyContainer;

$container = new DependencyContainer;

使用 set 方法设置类的定义

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

每次需要时都使用 get 方法调用定义的类

$object = $container->get(Foo::class);

使用 has 方法找出容器中是否已定义了接口

var_dump($container->has(Foo::class)); // true

注意:要将类设置为单例,请使用 singleton 方法

$container->singleton(Singleton::class, fn () => new SingletonClass);

贡献

要为此项目做出贡献,请按照以下步骤操作:遵循这些步骤

联系

Samuel do Prado Rodrigues (AssoDePicche) - samuelprado730@gmail.com