Symfony Tactician-bundle Typehints = Ошибка метода отсутствующего обработчика - PullRequest
0 голосов
/ 15 сентября 2018

Я использовал пакет thephpleague / tactician-bundle с Symfony и раньше, но впервые я использовал его с Symfony 4. * (в частности, 4.1.4) и пытался использовать один класс-обработчик для своего приложения.Сервис.

Когда я выполняю команду в контроллере

public function postAction(Request $request, CommandBus $commandBus)
{
    $form = $this->createForm(VenueType::class);
    $form->submit($request->request->all(), true);

    $data = $form->getData();

    if($form->isValid()) {
        $command = new CreateVenueCommand($data);
        $commandBus->handle($command);
        return $form->getData();
    }

    return $form;
}

... я получаю следующую ошибку:

"error": {
    "code": 500,
    "message": "Internal Server Error",
    "exception": [
        {
            "message": "Could not invoke handler for command App\\Application\\Command\\CreateVenueCommand for reason: Method 'handle' does not exist on handler",
            "class": "League\\Tactician\\Exception\\CanNotInvokeHandlerException",
            "trace": [

Я, кажется, следовал за установочные документы для комплекта поставки и установки его с помощью Flex.Насколько я могу судить, все настроено правильно, поэтому я не уверен, что мне не хватает в моей реализации.

Реализация

Согласно руководству по установке комплекта thephpleague / tactician-bundle I 'После установки с использованием Flex, пакет зарегистрирован и установлен пакет конфигурации:

tactician:
    commandbus:
        default:
            middleware:
                - tactician.middleware.locking
                - tactician.middleware.doctrine
                - tactician.middleware.command_handler

После создания класса команд DTO 'CreateVenueCommand' я создал класс обработчика:

use App\Infrastructure\Domain\Model\VenueRepositoryInterface;
use App\Application\Command\CreateVenueCommand;
use App\Domain\Entity\Venue;

class VenueApplicationService
{
    private $venueRepository;

    public function __construct(VenueRepositoryInterface $venueRepository)
    {
        $this->venueRepository = $venueRepository;
    }

    /**
     * @param CreateVenueCommand $aCommand
     * @throws \Exception
     */
    public function createVenue(CreateVenueCommand $aCommand)
    {
       $aVenue = new Venue($aCommand->getData())

        if ($aVenue === null) {
            throw new \LogicException('Venue not created');
        }

        $this->venueRepository->add($aVenue);

}

ЗатемЯ зарегистрировал класс обработчика как Сервис, используя преимущества автопроводки Symfony и шрифтов Tacticians:

    App\Application\VenueApplicationService:
        arguments:
            - '@App\Infrastructure\Persistence\Doctrine\DoctrineVenueRepository'
        tags:
           - { name: tactician.handler, typehints: true }

Таким образом, согласно установочным документам , шрифты работают, если:

  1. Метод должен быть общедоступным.
  2. Метод должен принимать только один параметр.
  3. Параметр должен быть напечатан с именем класса.

Кроме того, и это характерно для моего случая использования:

Если у вас есть несколько команд, поступающих в один обработчик, они все будут обнаружены, если они следуютправила выше.Фактическое имя метода НЕ важно.

Поэтому, когда я вызываю командную шину в классе контроллера, я не уверен, почему я получаю ошибку выше.

Если я изменю метод обработчика команд на:

public function handle(CreateVenueCommand $aCommand)
{

... тогда он будет работать нормально.Казалось бы, это говорит о том, что шрифты не работают так, как задокументировано.

В данном случае кажется, что фактическое имя метода IS важно. ... или я допустил какую-то форму ошибки в моей реализации ..или я неправильно понимаю несколько команд, входящих в один обработчик сценарий использования ??

Любая помощь будет принята с благодарностью.

Решение

Большое спасибо kunicmarko20 за то, что он указал мне правильное направление.

Специально для моего использованияслучай, когда мне просто нужно было использовать один из классов Tacticians MethodNameInflector, настроенный в Symfony таким образом:

tactician:
    commandbus:
        default:
            middleware:
                - tactician.middleware.locking
                - tactician.middleware.doctrine
                - tactician.middleware.command_handler
            method_inflector: tactician.handler.method_name_inflector.handle_class_name

... тогда это был просто вопрос присвоения имен каждому методу Handler в дескрипторе моего класса Application Service 'Команда

1 Ответ

0 голосов
/ 15 сентября 2018

Здесь в разделе 1. объясняется, как работает именование, если вы хотите использовать имя, отличное от указанного в этой таблице, вы можете реализовать интерфейс MethodNameInflector и предоставить имя метода.

...