digitalnoise / command-launcher-bundle
Requires
- php: >=8.1
- digitalnoise/command-launcher: ^v2.1
- symfony/framework-bundle: ^5.4|^6.0
Requires (Dev)
- phpunit/phpunit: ^10.0
- symfony/messenger: ^6.2
- symfony/phpunit-bridge: ^6.2
README
此包提供了使用Symfony CLI执行基于messenger结构的应用程序中任何消息(或命令)的功能。此类应用程序的示例之一是使用symfony/messenger或类似东西的应用程序(只要您使用将消息传递给调用单独处理器的总线结构,它就可以工作)。
这个包是做什么用的?
想象一个REST控制器,它将消息传递给注入的messenger。
// ... class ActivateUserController { // ... public function __invoke(Request $request): Response { $userId = UserId::fromRequest($request); $message = new ActivateUserMessage(UserId $id) $this->messageBus->dispatch($message); // ... } }
这是一个相当简单的示例,但它将引导我们到达要点。假设由于某种抽象原因,此路由不能使用,但您需要立即激活一个用户。当然,您可以编写一个小cli命令并在之后执行它。但可能会有更多复杂的情况。这些情况可能会使直接将消息传递给消息总线的可能性变得有用。
此包提供了从cli执行这些命令的可能性,而无需为每种情况编写单独的命令。
只需调用
bin/console digitalnoise:command:launch
这将提供命令/消息的列表。
[ActivateUser ] Acme\Message\ActivateUser
[DeleteUser ] Acme\Message\DeleteUser
[CreateSomething] Acme\Message\CreateSomething
> ActivateUser
在选择一个选项(例如,ActivateUser)后,您可以将所需的参数传递给消息。列表将看起来像上面的列表,只是带有您提供的用户ID和相关信息(它们的样式取决于您)。
设置
安装
使用此包的方式类似于所有Symfony包。以下步骤必须执行:
- 下载包
- 启用包
步骤1:下载包
打开命令行,进入项目目录,并执行以下命令以下载此包的最新稳定版本并将其添加到项目的依赖项中
composer require digitalnoise/command-launcher-bundle
步骤2:启用包
然后,通过在项目app/AppKernel.php文件中的registerBundles函数数组中添加新的Digitalnoise\CommandLauncherBundle\CommandLauncherBundle()来启用包
<?php // app/AppKernel.php // ... class AppKernel extends Kernel { public function registerBundles() { $bundles = array( // ... new Digitalnoise\CommandLauncherBundle\CommandLauncherBundle(), ); // ... } // ... }
使用包
您需要关注以下接口和类,以确保此包正常工作
Digitalnoise\CommandLauncher\CommandProvider
Digitalnoise\CommandLauncher\CommandLauncher
Digitalnoise\CommandLauncher\ParameterResolver
Digitalnoise\CommandLauncher\ParameterOption
1. CommandProvider接口
all()
函数将收集您的应用程序中的所有命令,并将它们传递给消息总线。由于任何应用程序都有自己的结构和messenger服务,您需要单独实现此函数。
/** * @return list<class-string> */ public function all(): array;
2. CommandLauncher接口
此接口负责执行消息。实现将使用消息总线作为类参数。launch(object $command)
函数将接收消息并将其传递到您的应用程序中使用的总线。
public function launch(object $command): void;
3. 抽象的ParameterResolver
abstract public function supports(string $class): bool; abstract public function options(string $class): array; ... abstract public function value(string $key): mixed; abstract public function manualValue(string $input): mixed;
让我们以用户激活为例。在这里,我们没有将字符串传递给消息,而是传递了UserId类的对象。
通过实现supports(string $class)
,您提供了有关为哪种类型的参数调用此解析器的信息。对于UserId类,它可能如下所示
public function supports(string $class): bool { return $class === UserId::class; }
由于您希望选择要激活哪个用户,您需要提供选项。以下代码显示了实现可能的样子。
所有用户对象将被加载并转换为ParameterOption
对象列表。
public function options(string $class): array { $users = $this->userRepository->all(); return array_map(fn(User $user) => new ParameterOption($user->getEmail(), $user->getFullName()), $users); }
最后,您需要定义实际值,当使用命令时,选择用户选项将返回此值。
public function value(string $key): mixed { // object of type UserId return $this->userRepository->findByEmail($key)->id(); }
让我们忽略这样一个事实:尽管在几秒钟前已经获取了用户信息,但仍然需要获取。您可以选择如何在您的UserIdProvider
类中保留数据。这是在构建消息时实际传递给消息的值。
public function manualValue(string $input): mixed { return UserId::fromString($input); }
自上次更新以来,可以定义一个手动输入值。如果由于任何意外原因某个选项没有被列出,您可以输入一个自定义值,这个值将在>manualValue
函数中处理。选项将默认列出,但如何实现手动输入的使用取决于您。
将所有这些放在一起并使用命令
您的services.yml
可能看起来像这样。在这个例子中,我们假设使用了thephpleague/tactician命令总线。
# We pass all command handlers with the tag tactician.handler to the command provider Acme\Command\CommandLauncher\CommandProvider: arguments: $handlers: !tagged_iterator tactician.handler Digitalnoise\CommandLauncher\CommandProvider: alias: 'Acme\Command\CommandLauncher\CommandProvider' Acme\Command\CommandLauncher\CommandLauncher: Digitalnoise\CommandLauncher\CommandLauncher: alias: 'Acme\Command\CommandLauncher\CommandLauncher' Acme\Command\CommandLauncher\Resolvers\UserIdResolver: Digitalnoise\CommandLauncherBundle\Command\CommandLauncherCommand: arguments: $parameterResolvers: - '@Acme\Command\CommandLauncher\Resolvers\UserIdResolver'
通过上述配置,我们应该已经集合了执行命令所需的类和信息,通过输入以下命令来执行:
bin/console digitalnoise:command:launch