lorenzo/piping-bag

CakePHP 4 插件,用于将 Ray.Di 作为依赖注入容器使用

安装次数: 104,302

依赖者: 1

建议者: 1

安全性: 0

星标: 35

关注者: 5

分支: 9

开放问题: 1

类型:cakephp-plugin

2.0 2020-11-25 12:55 UTC

This package is auto-updated.

Last update: 2024-09-05 14:11:19 UTC


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;
    }
}