code-mine/tactician-module

ZF2 模块,用于使用 League of Extraordinary Packages 的 Tactician 库 - 灵活的命令总线实现

2.0.1 2016-09-01 12:22 UTC

This package is not auto-updated.

Last update: 2024-09-13 22:32:20 UTC


README

Build Status Scrutinizer Code Quality Code Coverage Dependency Status Latest Stable Version Total Downloads License

包装模块,方便在您的 ZF2 应用程序中使用 Tactician 命令总线。

安装

最佳安装方式为 Composer

composer require mikemix/tactician-module

在您的 config/application.config.php 文件中将它注册为 ZF2 模块

    'modules' => [
        'YourApplicationModule',
        'TacticianModule',
    ],

使用

该模块提供了一个名为 Controller PlugintacticianCommandBus(),用于轻松分发命令。如果没有传递命令对象,将返回 CommandBus 对象。如果您传递了命令,它将被传递到 CommandBus 并处理,并返回处理程序的输出。

您可以在控制器中为该插件添加类型提示,例如:@method \League\Tactician\CommandBus|mixed tacticianCommandBus(object $command)

// Real life example.
// Namespaces, imports, class properties skipped for brevity

class LoginController extends AbstractActionController
{
    public function indexAction()
    {
        if ($this->request->isPost()) {
            $this->form->setData($this->request->getPost());

            if ($this->form->isValid()) {
                $command = new UserLoginCommand(
                    $this->form->getLogin(),
                    $this->form->getPassword()
                ));

                try {
                    $this->tacticianCommandBus($command);
                    return $this->redirect()->toRoute('home');
                } catch (\Some\Kind\Of\Login\Failure $exception) {
                    $this->flashMessenger()->addErrorMessage($exception->getMessage());
                    return $this->redirect()->refresh();
                }
            }
        }

        $view = new ViewModel();
        $view->setVariable('form', $this->form);
        $view->setTemplate('app/login/index');

        return $view;
    }
}

final class UserLoginCommand
{
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $password;
    }
}

final class UserLoginHandler
{
    // constructor skipped for brevity

    public function handle(UserLoginCommand $command)
    {
        $this->authenticationService->login($command->username, $command->password);
    }
}

如果您需要将命令总线注入到服务层或类似的地方,只需从 Service Manager 中使用 CommandBus 的 FQCN 即可。

<?php
namespace MyNamespace;

use League\Tactician\CommandBus;
use Zend\ServiceManager\ServiceManager;
use MyNamespace\Service\MyService;

class Module
{
    public function getServiceConfig()
    {
        return [
            'factories' => [
                MyService::class => function(ServiceManager $serviceManager) {
                    $commandBus = $serviceManager->get(CommandBus::class);
                    return new MyService($commandBus);
                },
            ],
        ];
    }
}

配置

该模块自带一个 ZendLocator、一个 CommandHandlerMiddleware 和一个 HandlerInflector,默认配置。如果您想覆盖默认的定位器或默认的命令总线实现,只需在合并的配置中使用 tactician 键。

'tactician' => [
    'default-extractor'  => League\Tactician\Handler\CommandNameExtractor\ClassNameExtractor::class,
    'default-locator'    => TacticianModule\Locator\ZendLocator::class,
    'default-inflector'  => League\Tactician\Handler\HandleInflector::class,
    'handler-map'        => [],
    'middleware'         => [
        CommandHandlerMiddleware::class => 0,
    ],
],

default-extractordefault-locatordefault-inflector 是服务管理器键,用于注册服务。

ZendLocator 期望 handler-map 中的处理程序在 commandName => serviceManagerKeycommandName => Handler_FQCN 中,尽管为了防止额外的成本检查,使用 serviceManagerKey 并确保它作为 Zend 服务可用。

要向中间件堆栈添加自定义中间件,将其添加到 middleware 数组中,作为 ServiceName => priority,其中中间件应执行(数字越高,执行越早)。例如

// ... your module config
'tactician' => [
    'middleware'         => [
        YourCustomMiddleware::class  => -100, // execute last
        YourAnotherMiddleware::class => 100, // execute early
    ],
],

基本用法

基本上,您可能想要做的所有事情,就是定义您的模块配置中的 handler-map 数组。例如

// module.config.php file

    return [
        // other keys
        'tactician' => [
            'handler-map' => [
                App\Command\SomeCommand::class => App\Handler\SomeCommandHandler::class,
            ],
        ],
    ];

插件

锁定中间件

现在可以直接使用 锁定中间件。只需将 League\Tactician\Plugins\LockingMiddleware FQCN 添加到 TacticianModule 的中间件配置中,并设置适当的优先级。您可能希望在其之前执行它。

// module.config.php file

    return [
        // other keys
        'tactician' => [
            'middleware' => [
                \League\Tactician\Plugins\LockingMiddleware::class => 500,
            ],
        ],
    ];

事务中间件

现在可以直接使用 事务中间件。只需将 League\Tactician\Doctrine\ORM\TransactionMiddleware FQCN 添加到 TacticianModule 的中间件配置中,并设置适当的优先级。您可能希望在其之前执行它,并在 LockingMiddleware 之后执行它。

// module.config.php file

    return [
        // other keys
        'tactician' => [
            'middleware' => [
                \League\Tactician\Doctrine\ORM\TransactionMiddleware::class => 250,
            ],
        ],
    ];

更改处理程序定位器

ClassnameZendLocator

此定位器简单地将单词 Handler 添加到命令的 FQCN,这样您就不必定义任何处理程序映射。例如,如果您请求命令 App\Commands\LoginCommand,定位器将尝试从服务管理器获取 App\Command\LoginCommandHandler

定位器可以与未在服务管理器中注册的 FQCN 一起使用,尽管为了防止额外的成本检查,请确保定位器已注册为可调用或工厂。

要将定位器从 ZendLocator 更改为 ClassnameZendLocator,只需在配置中设置即可。

// ... your module config
'tactician' => [
    'default-locator' => TacticianModule\Locator\ClassnameZendLocator::class,
],