Imagine that you already have a trustfully application that you have been running for a while, but there is a couple of common patterns that make you consider that you need a command line interface (CLI) for you application:

You are running some sort of cron that does a HTTP call to some endpoint to run some task on your website (like sending emails, etc)

You have some operation that you want to automate (using chef or something) and HTTP request may not play that nicely

You want to add some "super mega user" commands (like password reset or other) tha can be performed from command line, instead of hacking the DB.

Insert your own reason here ...

So, how do we do this? especially without reinventing the well?

The problem

Imagine that you have already a class on your application that performs your business logic, in this case, imagine that currently there is a form where you can edit a few values and then send the values to the server, that will be applied to the application by Example_Admin_ProcessConfigurationValues class bellow

<?php class Example_Admin_ProcessConfigurationValues { public function process(array $values) { // do some magic stuff with the configuration values } }

and now we want to supply the configuration values from command line as JSON file like this:

{ "configuration_key_a": "some value", "configuration_key_b": [ "value 1", "value 2", "value 3", ] "configuration_key_c": "other value }

So the goal is to be able to run a command like the following

php somecommand.php config.json

That means that we need to to the following steps:

Load the JSON file as a array Call Example_Admin_ProcessConfigurationValues::process with that array Done

Symfony Console Component to the rescue

Instead of reinvented the well we can use Symfony components to build this, I imagine that you are already using composer, so you should already have a composer.json file that will looks like this:

{ "name": "example/project", "license": "MIT", "require": { "php": ">=5.4.0" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "autoload": { "classmap": ["src/"] } }

Then you can just use the Symfony Console Component to be able to run your application from command line.

You just need to add symfony/console as a new dependency:

composer require symfony/console

And then you can create a new console command like the following example:

<?php use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class Example_Command_ConfigFromJsonCommand extends Command { protected function configure() { $this->setName('setup:load-json') ->setDescription('Load configurations values from a JSON file') ->addArgument( 'jsonFile', InputArgument::REQUIRED, 'Json file with configurations' ); } protected function execute(InputInterface $input, OutputInterface $output) { $jsonFile = $input->getArgument('jsonFile'); if (!file_exists($jsonFile)) { $output->writeln('Error: Json file does not exists'); return 1; } $jsonFileContent = file_get_contents($jsonFile); $config = json_decode($jsonFileContent, true); if (!is_array($config)) { $output->writeln('Error: Json file does not seams valid'); return 1; } // Call the existing code, with the content of the JSON file $oldClass = new Example_Admin_ProcessConfigurationValues(); $oldClass->process($config); return 0; } }

Alter that you need to register this, lets create a cli.php script that will be the entry point from the command line, and register the recently created command.

<?php require __DIR__.'/vendor/autoload.php'; use Symfony\Component\Console\Application; $application = new Application(); $application->add(new Example_Command_ConfigFromJsonCommand()); $application->run();

After that if you run cli.php from command line you should get this:

$ php cli.php Console Tool Usage: command [options] [arguments] Options: -h, --help Display this help message -q, --quiet Do not output any message -V, --version Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n, --no-interaction Do not ask any interactive question -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Available commands: help Displays help for a command list Lists commands setup setup:load-json Load configurations values from a JSON file

and to run your newly create command you just need to do:

php cli.php setup:load-json config.json

Done!