Symfony Tactician-bundle Typehints = 缺少处理程序方法错误

Posted

技术标签:

【中文标题】Symfony Tactician-bundle Typehints = 缺少处理程序方法错误【英文标题】:Symfony Tactician-bundle Typehints = Missing handler method error 【发布时间】:2019-02-20 00:43:23 【问题描述】:

我之前在 Symfony 中使用过 thephpleague/tactician-bundle,但这是我第一次在 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": [

我似乎遵循了 installation documents 的 tactician-bundle 并使用 Flex 安装了它。据我所知,一切都配置正确,所以我不确定我的实现中缺少什么。

实施

根据我使用 Flex 安装的 thephpleague/tactician-bundle 安装指南,并注册了捆绑包并安装了配置包:

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 

所以根据installation documents,类型提示在以下情况下起作用:

    方法必须是公开的。 该方法只能接受一个参数。 参数必须使用类名进行类型提示。

另外,这是针对我的用例的:

如果您有多个命令进入一个处理程序,只要它们遵循上述规则,它们都会被检测到。方法的实际名称并不重要。

所以当我在控制器类中调用命令总线时,我不确定为什么会出现上述错误。

如果我将命令处理程序方法更改为:

public function handle(CreateVenueCommand $aCommand)

...然后它工作正常。这似乎表明 typehints 没有按记录工作。

在这种情况下,方法的实际名称​​IS似乎很重要。 ...或者我在实现中犯了某种形式的错误...或者我误解了多个命令进入单个处理程序用例??

任何帮助将不胜感激。

解决方案

非常感谢 kunicmarko20 为我指明了正确的方向。

特别是对于我的用例,我只需要使用在 Symfony 中配置的 Tacticians MethodNameInflector 类之一:

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

...那么只需在我的应用程序服务类 'handlewhateverYouLikeCommand

中命名每个 Handler 方法即可

【问题讨论】:

【参考方案1】:

1. 下的Here 解释了命名的工作原理,如果您想使用与此表中不同的名称,您可以实现 MethodNameInflector 接口并提供方法的名称。

【讨论】:

以上是关于Symfony Tactician-bundle Typehints = 缺少处理程序方法错误的主要内容,如果未能解决你的问题,请参考以下文章

Symfony 2 还是 Symfony 1.4? [关闭]

Symfony控制器教程已开课

symfony/skeleton 和 symfony/website-skeleton

WordPress 作为 Symfony (Symfony3) 子目录

Symfony 4 捆绑包工作

从 Symfony 3.4 升级到 4:升级 symfony 时出错