lorenzo / piping-bag
CakePHP 4 插件,用于将 Ray.Di 作为依赖注入容器使用
Requires
- ray/di: ^2.1
Requires (Dev)
README
此插件可以在对象实例及其依赖项被使用之前配置它们,并将它们存储到容器类中以方便访问。
它使用干净灵活的Ray.Di 库,这是一个类似于“Google Guice”风格的 PHP 依赖注入框架。
Ray.Di 还允许您使用 AOP(面向方面编程)进行编程,即装饰配置的实例,以便在其方法之前或之后执行某些逻辑。
安装
您可以使用 composer 将此插件安装到您的 CakePHP 应用程序中。
composer require lorenzo/piping-bag=dev-master
配置
从 1.x 版本库升级(Cake 3.x)
已弃用
ControllerFactoryFilter.php
用于注入控制器ShellDispatcher.php
用于注入 shell 类
请在您的 config/bootstrap.php
文件中删除以下行:
DispatcherFactory::add('PipingBag\Routing\Filter\ControllerFactoryFilter'); Plugin::load('PipingBag', ['bootstrap' => true]);
控制器注入
为了使控制器中的注入工作,您需要在您的 Application.php
文件的 bootstrap
方法中添加以下行:
$this->addPlugin('PipingBag', ['bootstrap' => true]); $this->controllerFactory = new \PipingBag\Controller\DIControllerFactory();
Shell 注入
为了使控制器中的注入工作,您需要在您的 bin/cake.php
文件中添加以下行:
$commandFactory = new \PipingBag\Console\DICommandFactory(); $runner = new CommandRunner(new Application(dirname(__DIR__) . '/config'), 'cake', $commandFactory);
此外,您还可以在您的 config/app.php
文件中配置要使用的模块和缓存选项。
'PipingBag' => [ 'modules' => ['MyWebModule', 'AnotherModule', 'APlugin.SuperModule'], 'cacheConfig' => 'default' ]
您还可以将模块作为配置数组中的实例返回
'PipingBag' => [ 'modules' => [new App\Di\Module\MyWebModule()], 'cacheConfig' => 'default' ]
最后,如果您希望在它们注册之前调整模块,可以使用可调用函数
'PipingBag' => [ 'modules' => function () { return [new MyWebModule()]; }, 'cacheConfig' => 'default' ]
模块究竟是什么?
模块是描述实例及其依赖项应该如何构建的类,它们提供了一种自然的方式对配置进行分组。一个模块示例如下
// in app/src/Di/Module/MyModule.php namespace App\Di\Module; use Ray\Di\AbstractModule; class MyModule extends AbstractModule { public function configure() { $this->bind('MovieApp\FinderInterface')->to('MovieApp\Finder'); $this->bind('MovieApp\HttpClientInterface')->to('Guzzle\HttpClient'); $this->install(new OtherModule()); // Modules can install other modules } }
按照惯例,模块位于您的 src/Di/Module
文件夹中。有关创建模块以及如何将实例绑定到名称的更多信息,请参阅官方 Ray.Di 文档。
使用方法
在配置中创建并传递模块后,您可以获取任何类的实例,并按照模块中创建的规则解决它们的依赖项
use PipingBag\Di\PipingBag; $httpClient = PipingBag::get('MovieApp\HttpClientInterface');
在控制器中注入依赖项
Ray.Di 可以根据注解将实例注入到您的控制器中
// in src/Controller/ArticlesController.php use App\Controller\AppController; use MovieApp\HttpClientInterface; use Ray\Di\Di\Inject; // This is important class ArticlesController extends AppController { /** * @Inject */ public function setHttpClient(HttpClientInterface $connection) { $this->httpClient = $connection; } }
控制器创建后,所有具有 @Inject
注解的方法都将获得提示类实例。这也适用于构造函数。
在控制器动作中注入依赖项
您还可以直接在控制器动作中注入依赖项。在这种情况下,将类型提示的依赖项添加到参数的末尾,并将默认值设置为 null
,还需要使用 @Assisted
注解方法
// in src/Controller/ArticlesController.php use App\Controller\AppController; use MovieApp\HttpClientInterface; use PipingBag\Annotation\Assisted; // This is important class ArticlesController extends AppController { /** * @Assisted */ public function edit($id, HttpClientInterface $connection = null) { $article = $this->Articles->get($id) $connection->post(...); } }
在 Shell 中注入依赖项
Shell 也可以通过 @Inject
注解接收依赖项。但首先,您需要将 cake 控制台可执行文件更改为使用 PipingBag。打开您的 bin/cake.php
文件,使其看起来像这样:
// bin/cake.php ... exit(PipingBag\Console\ShellDispatcher::run($argv)); // Changed namespace of ShellDispatcher
然后,您可以对您的 Shell 应用注解
use Cake\Console\Shell; use Ray\Di\Di\Inject; // This is important class MyShell extends Shell { /** * @Inject */ public function setHttpClient(HttpClientInterface $connection) { $this->httpClient = $connection; } }