依赖注入和容器

v2.0 2020-10-02 06:00 UTC

This package is auto-updated.

Last update: 2024-09-24 01:47:52 UTC


README

依赖注入和容器

通过composer安装

composer require nezamy/di

然后加载composer自动加载

require __DIR__ . '/vendor/autoload.php';

用法

假设我们有一个Book类,并且我们需要调用getName方法。无论这个方法是否为静态。

class Book
{
    private string $name = 'First Book';

    public function getName(): string
    {
        return $this->name;
    }
}

$resolver = new Just\DI\Resolver;
$resolver->resolve($resolver->prepare([Book::class, 'getName']));
//Or 
$resolver->resolve([new Book, 'getName']);
// the both returns 'First Book'

也许你没有使用new实例来调用Book,你应该使用第一个示例中的prepare方法。

带有参数调用方法

现在我们有一个带有一个参数的新方法

class Book
{
    private string $name = 'First Book';

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): void
    {
        $this->name = $name;
    }
}

$container = Just\DI\Container::instance();
$container->setVar('name', 'PHP');

$book = new Book();
$resolver = new Just\DI\Resolver; 
$resolver->resolve([$book, 'setName']);
$book->getName();
// will return 'PHP'

我们没有带参数调用setName,但是我们在上面的容器中设置了name作为一个全局变量。解析器将在容器中查找,如果找到了与参数同名变量,则传递它,如果没有找到,则传递null。

对象类型参数 & 单例

$function = function(Book $book){
    return $book->getName();
};

$container = Container::instance();
$resolver = new Resolver;
$name = $resolver->resolve($function);
//here $name returns 'First Book' because it's initial value


$book = new Book();
$book->setName('Test Book');
// for define a singleton object
$container->set(Book::class, $book);

$resolver = new Resolver;
$name = $resolver->resolve($function);
$this->assertSame('Test Book', $name);
//$name now is equal 'Test Book'

调用一个具有构造函数的类中的方法,并且构造函数需要两个参数

class User{
    private string $name;
    private string $email;
    
    public function __construct(string $name, string $email)
    {
        $this->name = $name;
        $this->email = $email;
    }
    
    public function getName(): string
    {
        return $this->name;
    }
    
    public function getEmail(): string
    {
        return $this->email;
    }
}

$container = Just\DI\Container::instance();
$container->setVar('name', 'Mahmoud Elnezamy');
$container->setVar('email', 'mahmoud@nezamy.com');

$resolver = new Just\DI\Resolver;
$name = $resolver->resolve($resolver->prepare([User::class, 'getName']));
// name here will return 'Mahmoud Elnezamy'

魔术调用

class User{
    private string $name;
    private string $email;
    
    public function __construct(string $name, string $email)
    {
        $this->name = $name;
        $this->email = $email;
    }
    
    public function getName(): string
    {
        return $this->name;
    }
}
class Book
{
    public function Auther(User $user){
        return $user->getName();
    }
}

$container = Just\DI\Container::instance();
$container->setVar('user', ['Mahmoud', 'email@domain.com']);
$container->setMagicCall(User::class, function ($attr, $value){
    return new User(...$value);
});

$resolver = new Just\DI\Resolver;
$book = $resolver->resolve(
    $resolver->prepare([Book::class, 'Auther'])
);
//$book will return 'Mahmoud'

API

$container = \Just\DI\Container::instance();

$container->setVar('name', 'value');
$container->getVar('name');
$container->hasVar('name');
$container->importVars([
    'name' => 'name here',
    'id' => '1'
]);

$container->set('className', new stdClass());

//Maybe the new instance do some processing or load some configurations or connect with database.
//and you won't to make the instance until the first use or call
$container->set('className', function (){
    return new stdClass();
});
$container->get('className');
$container->has('className');
// define some singleton objects
$container->import([
    Request::class => new Request(...),
    Response::class => new Response(...),
    DB::class => new DB('user', 'pass',...)
]);

$container->setMagicCall('UserModel', function ($attr, $value){
    if($attr == 'id'){
       return new UserModel($value);
    }
    return null;
});
$container->getMagicCall('UserModel');
$container->hasMagicCall('UserModel');