acelot / resolver
PHP 7 和 8 的依赖自动解析器
Requires
- php: ^7.3 || ^8.0
- psr/container: ^1.0
Requires (Dev)
- phpunit/phpunit: ^9.0
- vimeo/psalm: ^4.8
This package is auto-updated.
Last update: 2024-09-20 15:02:14 UTC
README
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()
方法在调用之间共享。此方法在 FactoryDefinition
和 ObjectDefinition
中可用。ValueDefinition
按设计总是共享。
Resolver(c)由 Valeriy Protopopov 编写。
Resolver 遵循 MIT 许可证。