2 minutes
Console Commands in an Expressive Applicaton
In a current customer project, I needed the ability to run commands from the CLI.
Symfony provides a console component which is, among others, used by zendframework/zend-expressive-tooling
. The documentation got me off to a quick start and I got my first Hello
command running within minutes.
I wanted to provide a re-usable package, where the implementation can provide the definition of a command list.
Since I am not using the package within a Symfony application, I needed somehow access to the Service Container of the Expressive application. I quick search on the internet did not show up any useful results and I was left to use my own brain.
My starting point was the public/index.php
provided by Expressive. From there it was just a small step of adjustments and I could access the configuration by simply loading the service container via $container = require 'config/container.php';
.
The next task was to use a factory service for commands that have dependencies. Since I already have the service container, I can simply get the command from it.
The end-result looks like so:
#!/usr/bin/env php
<?php
declare(strict_types = 1);
namespace Arueckauer\Console;
use PackageVersions\Versions;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
require 'vendor/autoload.php';
/** @var ContainerInterface $container */
$container = require 'config/container.php';
$commandsConfig = require 'config/autoload/commands.global.php';
$commandList = [];
foreach ($commandsConfig[CommandList::class] as $command) {
if ($command instanceof Command) {
$commandList[] = $command;
} else {
$commandList[] = $container->get($command);
}
}
$application = new Application('Console');
$application->addCommands($commandList);
$application->run();
The configuration of commands is placed in a configuration file like config/autoload/commands.global.php
.
<?php
declare(strict_types = 1);
use Command\Hello;
use Command\NeedSomeDependencies;
use Elstr\Console\CommandList;
return [
CommandList::class => [
new Hello(),
NeedSomeDependencies::class,
],
];
A day after I completed my implementation, two users mentioned an interesting post by Geert Eltink (aka @xtreamwayz) from 2016 zend-expressive console cli commands and the zfcampus/zf-console library.
(I blacked out the usernames, since I do not have their permission to use them.)
Update 2019-10-18: In an additional post, I show two more real-world examples.