Commands

Service Name: Services::COMMANDS

Symfony Console’s commands are each of the actions that can be executed by an end-user of the migrations library. However we took a slightly different approach with commands than usual:

Commands vs Messages & Handlers

One of the things that we found annoying in other migration libraries is that almost everything had to be configured before you could even execute a basic library command in the console. For example, in some libraries you can’t even get help about available commands without first configuring your database connection - which usually doesn’t make much sense.

In order to solve that issue Baleen CLI decouples the Command definition from its execution (this might in fact be a good feature for future SymfonyConsole versions). This decoupling is facilitated by League\Tactician together with League\Container to gather application dependencies ONLY once they’re actually needed. This allows end-users to query the help for your executable without having to configure a database connection, because the database connection will only be instantiated when its ACTUALLY needed.

Tip

All of this happens behind the scenes so you don’t have to worry about it. Refer to the BaseCommand class for more information.

Since we’re using a CommandBus library, we decided to disambiguate the meaning of Command as follows:

  • Whenever we refer to Commands we mean Symfony\Console commands, and we’ll mark them with bold. E.g. status, or migrate.
  • But whenever we refer to Messages, we refer to a “command message” from the CommandBus pattern. These messages are classes whose name ends with “Message”, e.g. “StatusMessage” or “MigrateMessage” - which correspond to the example commands on the previous item (they provide the command definition to Symfony\Console).

Customizing Commands

The list of available commands is configured and provided by CommandsProvider, which also allows for a flexible way to customize them:

  1. Create your own commands provider class.

  2. Have it extend CommandsProvider.

  3. Add a public constructor and use it to customize the contents of the $commands protected property. E.g.:

    /**
     * Example from Doctrine Migrations
     * __construct
     */
    public function __construct()
    {
        // custom message and custom handler
        $this->commands[Services::CMD_REPOSITORY_CREATE] = [
            'message' => CreateMessage::class,
            'handler' => CreateHandler::class,
        ];
    
        // customize message only - use default handler
        $this->commands[Services::CMD_TIMELINE_EXECUTE]['message'] = ExecuteMessage::class;
    
        // custom message and custom handler
        $this->commands[Services::CMD_TIMELINE_MIGRATE] = [
            'message' => MigrateMessage::class,
            'handler' => MigrateHandler::class,
        ];
        BaseCommandsProvider::__construct();
    }
    
  4. Overwrite the default commands provider by supplying a reference to your own inside config/providers.php.

In other words, adding or modifying commands is as simple as extending the default CommandsProvider and customizing the $commands property to point to the correct messages and handlers. The base CommandsProvider will do the rest of the work for you.