acelot/resolver

PHP 7 和 8 的依赖自动解析器

2.4.0 2021-07-20 08:15 UTC

This package is auto-updated.

Last update: 2024-09-20 15:02:14 UTC


README

Build Status Code Climate

Resolver 是 PHP 7 和 8 的依赖自动解析器。支持 PSR-11 ContainerInterface

安装

composer require acelot/resolver

为什么?

想象一下,你有一个控制器

class UsersController
{
    public function __construct(UsersService $service)
    {
        // ...
    }
}

如你所见,控制器在构造函数中需要 UsersService。为了解析这个依赖,你可以直接传递一个 UsersService 的新实例。让我们试试这个

$service = new UsersService();
$controller = new UsersController($service);

这是不行的,因为 UsersService,反过来,需要 UsersRepository 来访问数据。

class UsersService
{
    public function __construct(UsersRepository $repository)
    {
        // ...
    }
}

好的,让我们创建一个仓库实例!

$repository = new UsersRepository();
$service = new UsersService($repository);
$controller = new UsersController($service);

不幸的是,这仍然不行,因为我们遇到了新的依赖!出人意料的是,仓库需要一个数据库连接 :)

class UsersRepository
{
    public function __construct(Database $db)
    {
        // ...
    }
}

你说“吃这个!”。

$db = new Database('connection string here');
$repository = new UsersRepository($db);
$service = new UsersService($repository);
$controller = new UsersController($service);

成功了!我们最终创建了 UsersController 的实例!现在想象一下,你有十个或一百个这样的控制器!使用 Resolver,你可以极大地简化类的创建。这代码使用 Resolver 就是这样

$resolver = new Resolver([
    Database::class => ObjectDefinition::define(Database::class)->withArgument('connectionString', 'connection string here')
]);

$controller = $resolver->resolve(UsersController::class);

就这么多。

它是如何工作的?

Resolver 通过使用 反射 来解析类。通过反射,Resolver 找出类的所有依赖,以及依赖的依赖,以此类推。当 Resolver 达到最深的依赖时,它开始逐个创建这些类的实例,直到顶级类。解析后的类存储在本地数组中,以避免重复解析。

可用定义

  • FactoryDefinition(简写为 factory()
  • ObjectDefinition(简写为 object()
  • ValueDefinition(简写为 value()

实例共享

解析后的定义可以通过 ->shared() 方法在调用之间共享。此方法在 FactoryDefinitionObjectDefinition 中可用。ValueDefinition 按设计总是共享。

Resolver(c)由 Valeriy Protopopov 编写。

Resolver 遵循 MIT 许可证。