jschreuder / middle-di
可类型提示的依赖注入容器。
dev-master
2023-02-08 22:32 UTC
Requires
- php: >=8.0
Requires (Dev)
This package is auto-updated.
Last update: 2024-09-09 02:15:30 UTC
README
一个PHP依赖注入容器库,旨在允许以原生PHP进行服务和工厂定义,以便进行类型提示、自动检查和代码补全。它通过即时重写类来实现,并确保服务定义始终返回相同的实例。
除了核心功能外,它还允许在文件系统中缓存生成的代码,从而允许OP缓存在生产环境中工作。它还包含了一些用于配置传递的逻辑。
约定
所有服务定义应该是以"get"开始的公共方法,所有工厂应该以"new"开头。目前只强制执行服务定义,其他规则包括:它只能接受一个字符串名称(见下文)作为参数,并且必须有单一返回类型,该类型是类或接口。
<?php use jschreuder\MiddleDi\DiCompiler; class Container { // This will be rewritten to always return the same object public function getDatabase(): PDO { return new PDO(); } // A service using the database public function getService(): Service { return new Service($this->getDatabase()); } // This will be left alone and work as defined public function newObject(): stdClass { return new stdClass(); } } // Create the compiled container $dic = (new DiCompiler(Container::class))->compile()->newInstance(); // these will all be true var_dump( $dic instanceof Container, $dic->getDatabase() === $dic->getDatabase(), $dic->getService() === $dic->getService(), $dic->newObject() !== $dic->newObject() );
使用不同名称的实例化服务
尽管预期服务应该是单例,但在命名时允许使用多个服务实例。支持第一个参数,它将被视为其名称,并可用于在配置中区分。
<?php class Container { public function getDatabase(): PDO { return new PDO(); } // This will return different instances for different names public function getTableService(string $name): TableService { return new TableService($name, $this->getDatabase()); } }
在生产环境中将容器缓存在文件系统中
为了允许op-caching工作,并尽可能使生产环境中的事物变得尽可能快,可以将编译后的容器缓存到文件中。
<?php use jschreuder\MiddleDi\DiCompiler; use jschreuder\MiddleDi\DiCachedCompiler; class Container {} // Create the compiled container $compiler = (new DiCachedCompiler( new DiCompiler(Container::class), new SplFileObject('path/to/cachefile.php', 'c'); ))->compile(); $dic = $compiler->newInstance();
添加配置
包含了一个简单的配置助手ConfigTrait
。它添加了一个构造函数,该构造函数接受数组或ArrayAccess实例,并允许使用config()方法请求配置项。当请求不存在的配置项时,它将抛出异常。
<?php use jschreuder\MiddleDi\DiCompiler; class Container { use jschreuder\MiddleDi\ConfigTrait; // This will be rewritten to always return the same object public function getDatabase(): PDO { return new PDO($this->config('db.dsn')); } } // Create the compiled container $config = ['dsn' => 'example:dsn']; $dic = (new DiCompiler(Container::class))->compile()->newInstance($config);