承接 digitalnoise/command-launcher-bundle 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

digitalnoise/command-launcher-bundle

Composer 安装命令:

composer require digitalnoise/command-launcher-bundle

包简介

README 文档

README

Total Downloads MIT License

This bundle provides functionality to execute any message (or command) of an application which has messenger based structure, using the Symfony CLI. An example for such applications would be one, that makes use of the symfony/messenger or something similar (as long as you use a structure, that passes a message to a bus which calls a separate handler, it works).

What is this bundle for?

Imagine a REST-Controller which passes a message to the injected messenger.

// ...
class ActivateUserController
{
    // ...
    public function __invoke(Request $request): Response
    {
        $userId = UserId::fromRequest($request);
        $message = new ActivateUserMessage(UserId $id)
        
        $this->messageBus->dispatch($message);
        
        // ...
    }
}

This is a pretty simple example, but this will lead us to the point. Let's assume, that this route cannot be used for some abstract reason, but you need to activate a user immediately. Of course, you can write a small cli command and execute it afterwards. But there could be much more complex cases. Those could make it useful, to have the possibility, to pass those messages directly to the message bus.

This bundle provides the possibility to execute those commands from the cli without writing separate commands for each case.

Simply by calling:

bin/console digitalnoise:command:launch

This will provide a list of commands/messages.

[ActivateUser   ] Acme\Message\ActivateUser
[DeleteUser     ] Acme\Message\DeleteUser
[CreateSomething] Acme\Message\CreateSomething
> ActivateUser

After choosing an option (e.g., ActivateUser), you can pass the required parameter to the message. The list will look as the list above, just with your provided user ids with the related information (it's up to you, how they'll look like).

Setup

Installation

Using this package is similar to all Symfony bundles. The following steps must be performed

  1. Download the bundle
  2. Enable the bundle

Step 1: Download the bundle

Open a command console, enter your project directory, and execute the following command to download the latest stable version of this bundle and add it as a dependency to your project:

composer require digitalnoise/command-launcher-bundle

Step 2: Enable the bundle

Then, enable the bundle by adding new Digitalnoise\CommandLauncherBundle\CommandLauncherBundle() to the bundles array of the registerBundles function in your project's app/AppKernel.php file:

<?php

// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ...

            new Digitalnoise\CommandLauncherBundle\CommandLauncherBundle(),
        );

        // ...
    }

    // ...
}

Using the bundle

You need to take care for the following interfaces and classes, to make this bundle work:

Digitalnoise\CommandLauncher\CommandProvider
Digitalnoise\CommandLauncher\CommandLauncher
Digitalnoise\CommandLauncher\ParameterResolver

Digitalnoise\CommandLauncher\ParameterOption

1. The CommandProvider interface

The function all() will gather all commands inside your application which will be passed to the message bus. Since any application has its own structure and messenger service, you need to implement this function individually.

/**
 * @return list<class-string>
 */
public function all(): array;

2. The CommandLauncher interface

This interface is responsible for the execution of a message. The implentation will take a message bus as class parameter. The launch(object $command) function will receive a message and pass it to the used bus inside your application.

public function launch(object $command): void;

3. The abstract 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;

Let's call the upper example with the user activation to mind. Here, we don't pass a string to the message, but rather an object of the class UserId.

By implementing supports(string $class), you provide the information, for which type of parameter, this resolver shall be called. In case of the UserId class, it would look as follows:

public function supports(string $class): bool
{
    return $class === UserId::class;
}

As you want to choose, which user will be activated, you need to provide options. The following code shows an example, how the implementation could look like.

All user objects will be loaded and transformed to a list of ParameterOption objects.

public function options(string $class): array
{
    $users = $this->userRepository->all();

    return array_map(fn(User $user) => new ParameterOption($user->getEmail(), $user->getFullName()), $users);
}

Finally, you need to define the actual value, which will be returned by choosing a user option, when using the command.

public function value(string $key): mixed
{
    // object of type UserId
    return $this->userRepository->findByEmail($key)->id();
}

Let's ignore the fact, that the user will be fetched inspite of being so some seconds before. It's your choice, how you want to hold the data inside your UserIdProvider class. This is the value, which is actually passed to the message, when it's built.

public function manualValue(string $input): mixed
{
    return UserId::fromString($input);
}

Since the last update, it is possible to define a manual input value. In the case, that an option won't be listed for any unexpected reason, you can type a custom value and this one will be process inside the manualValue function. The option will be listed by default, but the implementation, how the manual input will be used, is up to you.

Bring it all together and use the command

Your services.yml could look like this. In this example, we assume, that the thephpleague/tactician command bus is used.

# 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'

With the configuration above, we should have brought together the necessary classes and information to execute the command by typing

bin/console digitalnoise:command:launch

digitalnoise/command-launcher-bundle 适用场景与选型建议

digitalnoise/command-launcher-bundle 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2023 年 01 月 27 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 digitalnoise/command-launcher-bundle 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 digitalnoise/command-launcher-bundle 我们能提供哪些服务?
定制开发 / 二次开发

基于 digitalnoise/command-launcher-bundle 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 2k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 5
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 2
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2023-01-27