- Using the Symfony2 Dependency Injection Container as a standalone component
- Launching PHPUnit tests from a browser with Symfony2
- Using the Console component to write an interactive installer for Composer
This post is part of the ”Symfony2 components in your own userland” series; here is a list of all the articles contained this series:
Today we are going to see the power of Symfony2’s Console component, which lets us build powerful interactive command line applications in pure PHP.
In this episode we are going to create an interactive shell able to generate new composer-based projects: we will have a command to define which dependencies we need and another one to:
- create the installation directory
- download composer
- generate a
composer.json
according to the required dependencies - run a
php composer.phar install
to install everything
The approach we’re going to use will be very rough and incomplete: no error handling, no decent abstraction, but is intended to give you a clue about the potentiality of the CLI tool and to show you how you can easily create PHP command line applications without the need to write too much good code.
Approach and installation
The Symfony2 Console lets use extend the Console\Command\Command
class to
implement your own commands, so we will add a couple custom commands, one to
register dependencies and one to execute the installation.
First of all, let create our own composer.json
, to download the Console
and Process1
components:
1 2 3 4 5 6 7 |
|
then install everything and create your installer.php
script which
serves as the entry point for the console:
1 2 3 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
In the installer.php
we are instantiating a new interactive shell
application, adding to it 2 new commands and then we run it: don’t try it now,
as the added command classes don’t exist yet.
A container for the dependencies
The first custom command we are going to add is a dependency container, which is
a convenient class storing the dependencies, like symfony/yaml
, in an
attribute, and exposes a getDependencies()
method that will be used by the
installer command to retrieve the dependencies to install.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
As you see, the command will be called when doing a add-dependency
from the console
and will ask the user to prompt the dependency we wants to add; a basic check is done:
1 2 3 4 5 6 7 8 9 |
|
Note that, for being quick’n’dirty, we store the dependencies in the composer way:
1
|
|
and we use master
as the only version available2.
This is it: now we only need to create the command to install everything.
The installation command
The Install
command will be called with install
from the command line, and
executes 4 sub-tasks to finish the installation process:
- create the installation directory
- download composer via
wget
- generate the
composer.json
according to the dependencies specified in the DependencyContainer - run the composer traditional installation (
php composer.phar install
)
This command takes a DependencyContainer
argument in the constructor
to extract the dependencies needed to be installed:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|
as you see we execute this 4 tasks and, if an error happens, we output an error, otherwise a confirmation message tells the user that everything went fine.
If a failure happens, we get the error message thanks to the Process
method getErrorOutput()
.
Let’s see how the tasks are implemented in this class: first of all, we need a createInstallationDirectory()
method that launches a new mkdir
process and returns a boolean value, indicating the
successfulness of the process; before returning false, the class’ internal attribute
$failingProcess
is updated:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
As you see, the user will be asked to provide an $installDir
in which we are going
to execute the whole process.
Now we need to create the downloadComposer()
method, which uses wget
to put composer.phar
in the installation directory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Then we generate a composer.json
in the installation directory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Note that you will need a template file to do so:
1 2 3 4 5 |
|
The last step consists in launching a new process which runs the usual composer’s installation process on the installation directory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
This is the console output for generating a new project which depends on
symfony/yaml
and symfony/dom-crawler
:
The auto-generated composer.json
will look like:
1 2 3 4 5 |
|
Conclusion
As said, this implementation is pretty naive and can definitely be improved: but with a couple classes and basic logic you are able to write a powerful tool that doesn’t require a web frontend and runs directly from the command line with a pure implementation in PHP, thanks to the Symfony2 components.