Creating new Commands and Handlers

Commands are the C of the CQRS paradigm. To change the state of the domain you should use a command. Commands should have all the data they need to be handled properly passed in their constructor parameters.

Commands should be immutable data-moving objects. All parameters should be passed by constructor. Don’t use setters when building a command.

Create a command class

To create a command, you need to create a command class. In the example below, the added command extends CampaignCommand to add shared methods in all of the Campaign commands. If a shared command base exists for your bounded context, use it as needed to keep the code DRY.

// backend/src/Application/Campaign/Command/SendNewCampaignAvailableNotification.php

namespace OpenLoyalty\Application\Campaign\Command;

use OpenLoyalty\Domain\Core\Id\CampaignId;

/**
 * Class SendNewCampaignAvailableNotification.
 */
class SendNewCampaignAvailableNotification extends CampaignCommand
{
    /**
     * @var array
     */
    private $recipientTokens;

    /**
     * @var string
     */
    private $title;

    /**
     * @var string
     */
    private $message;

    /**
     * @var array
     */
    private $labels;

    /**
     * SendNewCampaignAvailableNotification constructor.
     *
     * @param CampaignId $campaignId
     * @param string     $title
     * @param string     $message
     * @param array      $labels
     * @param array      $recipientTokens
     */
    public function __construct(
        CampaignId $campaignId,
        string $title,
        string $message,
        array $labels,
        array $recipientTokens
    ) {
        parent::__construct($campaignId);
        $this->title = $title;
        $this->message = $message;
        $this->labels = $labels;
        $this->recipientTokens = $recipientTokens;
    }
}

Create a command handler class

The next thing to do is to create a CommandHandler class. Notice the use of the Handler suffix in the class name.

// backend/src/Application/Campaign/CommandHandler/NotificationHandler.php

namespace OpenLoyalty\Application\Campaign\CommandHandler;

use Broadway\CommandHandling\SimpleCommandHandler;
use OpenLoyalty\Application\Campaign\Command\SendNewCampaignAvailableNotification;
use OpenLoyalty\Infrastructure\User\Notification\NotificationServiceInterface;

class NotificationHandler extends SimpleCommandHandler
{
    /**
     * @var NotificationServiceInterface
     */
    private $notificationService;

    /**
     * NotificationHandler constructor.
     *
     * @param NotificationServiceInterface $notificationService
     */
    public function __construct(
        NotificationServiceInterface $notificationService
    ) {
        $this->notificationService = $notificationService;
    }

    /**
     * @param SendNewCampaignAvailableNotification $command
     *
     * @throws \OpenLoyalty\Infrastructure\User\Notification\NotImplementedException
     */
    public function handleSendNewCampaignAvailableNotification(SendNewCampaignAvailableNotification $command): void
    {
        $this->notificationService->sendRewardAvailableNotification($command->toArray());
    }
}

Note

Remember that the function name must be created with the handle prefix and command name in camel case.

Command class Handler function name
SendNewCampaignAvailableNotification handleSendNewCampaignAvailableNotification
AnotherExampleNotification handleAnotherExampleNotification

Register a command handler

Then you need to register the Command handler class in application.yml

// backend/src/Infrastructure/Campaign/Resources/config/application.yml

services:
    OpenLoyalty\Application\Campaign\CommandHandler\NotificationHandler:
        tags:
            - { name: broadway.command_handler }

Note

If every thing is wired up and working don’t forget to write tests!