yjx/easy-di

一个简单的依赖注入容器,实现了Psr-11。

v1.0.3 2018-08-14 02:18 UTC

This package is auto-updated.

Last update: 2024-08-29 04:02:13 UTC


README

EasyDI是一个具有自动依赖注入的小型容器,遵循PSR-11。

具体详细介绍及讨论请参见博客

容器提供方法

  • raw(string $id, mixed $value)
    适用于保存参数,$value可以是任何类型,容器不会对其进行解析。

  • set(string $id, \Closure|array|string $value, array $params=[], bool $shared=false) 定义服务

  • singleton(string $id, \Closure|array|string $value, array $params=[]) 等同调用set($id, $value, $params, true)

  • has(string $id) 判断容器是否包含$id对应条目

  • get(string $id, array $params = [])
    从容器中获取$id对应条目,可选参数$params可优先参与到条目实例化过程中的依赖注入

  • call(callable $function, array $params=[]) 利用容器来调用callable,由容器自动注入依赖。

  • unset(string $id) 从容器中移除$id对应条目

安装 Installation

使用 Composer 安装EasyDi

composer require yjx/easy-di

基本使用 Basic Usage

容器的实例化

use EasyDi\Container();

$container = new Container();

EasyDI容器管理两种类型的数据:服务 和 参数(raw)

定义服务和参数

use Psr\Container\ContainerInterface;
use EasyDI\Container();

$c = new EasyDI\Container();

// 定义参数
$c->raw('redis.host', "127.0.0.1");

// 使用闭包
$c->set('redis', function(ContainerInterface $c) {
  $redis = new Redis();
  $redis->pconnect($c->get('redis.host'));
  return $redis;
}, [], true);

$reids = $c->get('redis');  // 由于set时第4个参数$shared设置为true, 因此每次获取的都是同一个对象

闭包中的参数$c由于使用了类型指示,因此EasyDI会自动完成依赖注入(将它自身注入).

自动依赖解决

示例1

直接拿PHP-DI官方演示代码

class Mailer
{
    public function mail($recipient, $content)
    {
        // send an email to the recipient
    }
}

class UserManager
{
    private $mailer;

    public function __construct(Mailer $mailer)
    {
        $this->mailer = $mailer;
    }

    public function register($email, $password)
    {
        // The user just registered, we create his account
        // ...

        // We send him an email to say hello!
        $this->mailer->mail($email, 'Hello and welcome!');
    }
}

$c = new EasyDI\Container();
$userManager = $c->get('UserManager');

// 等价执行
//$mailer = new Mailer();
//$userManager = new UserManager($mailer);

示例2

class ClassA
{
    protected $b;
    protected $say;

    public function __construct(ClassB $b, ClassC $c, $say="hello")
    {
        $this->b = $b;
        $this->say = $say;
    }

    public function saySth()
    {
      return "{$this->say} {$this->b->saySth()}";
    }
}

class ClassB
{
    protected $msg;

    public function __construct($msg)
    {
        $this->msg = $msg;
    }

    public function saySth()
    {
        return $this->msg;
    }
}

class ClassC
{
}

// 容器实例化
$c = new EasyDI\Container();

// 最基础的配置方式, 未用到容器的依赖注入特性
$c->set('basic', function () {
    return new ClassA(new ClassB("easy-di"), new ClassC(), "I like");
});
$basicService = $c->get('basic');
echo $basicService->saySth().PHP_EOL;   // 输出: I like easy-di

// 利用容器自动解决依赖
$c->set(ClassB::class, ClassB::class, ['easy-di']);         // 配置ClassB的标量依赖, params 等同配置 ['msg'=>"easy-di"]
$c->set('advance', ClassA::class, [2=>"I really like"]);    // 配置advance服务, params 等同配置 ['say'=>"I really like"]
$advanceService = $c->get('advance');                       // ClassA实例化所需的第2个参数$c由容器自动生成实例
echo $advanceService->saySth().PHP_EOL; // 输出: I really like easy-di

示例3 call()

```php
class UserManager
{
    private $mailer;

    public function __construct(Mailer $mailer)
    {
        $this->mailer = $mailer;
    }

    public function register($email, $password)
    {
        // The user just registered, we create his account
        // ...

        // We send him an email to say hello!
        $this->mailer->mail($email, 'Hello and welcome!');
    }

    public function quickSend(Mailer $mailer, $email, $password)
    {
        $mailer->mail($email, 'Hello and welcome!');
    }
}

function testFunc(UserManager $manager)
{
    return "test";
}

// 实例化容器
$c = new EasyDI\Container();

// 输出: 'test'
echo $c->call('testFunc')."\n";	

// 输出: 'test'
echo $c->call(function (UserManager $tmp) {
    return 'test';
});	

// 自动实例化UserManager对象	[$className, $methodName]
$c->call([UserManager::class, 'register'], ['password'=>123, 'email'=>'[email protected]']);	

// 自动实例化UserManager对象	$methodFullName
$c->call(UserManager::class.'::'.'register', ['password'=>123, 'email'=>'[email protected]']);	

// 调用类的静态方法	[$className, $staticMethodName]
$c->call([UserManager::class, 'quickSend'], ['password'=>123, 'email'=>'[email protected]']);	

// 使用字符串调用类的静态方法 $staticMethodFullName
$c->call(UserManager::class.'::'.'quickSend', ['password'=>123, 'email'=>'[email protected]']);	

// [$obj, $methodName] 
$c->call([new UserManager(new Mailer()), 'register'], ['password'=>123, 'email'=>'[email protected]']);	

// [$obj, $staticMethodName]
$c->call([new UserManager(new Mailer()), 'quickSend'], ['password'=>123, 'email'=>'1@1.1']);