Using Symfony Console Component in Zend application
Zend Framework is good when it comes to web requests, involving controllers with their actions, but usually most web applications today have another entry point: running from console. Some examples of console tasks: clearing up cache, sending emails, seeding a database, extracting/merging translatable strings and generally any kind of batch jobs. At first, I’ve kept a directory of runnable scripts for this, but after some time, I realized the need to unify and organize this messy collection of scripts. Symfony Console Component elegantly solves this kind of problem, providing solid platform for building CLI applications. Being one of the core components of Symfony2 framework, it’s already intensively used in the framework itself and other PHP projects. If you are new to Symfony Console, I suggest checking out these links:
Let’s see how could we integrate it into Zend application. Suppose we have a Zend application with the structure similar to the recommended one and ~/cli-show
is a root directory. Symfony Console requires PHP >= 5.3, version of Zend framework being used is 1.11.8.
Installing Symfony Console
I’m going to install it from Git. In real project, we’ll probably use git’s submodule functionality or download the archive from Github and unzip it, but for the sake of simplicity, let’s just clone it now.
[/]$ cd ~/cli-show
[cli-show]$ mkdir -p library/Symfony/Component
[cli-show]$ git clone https://github.com/symfony/Console.git library/Symfony/Component/Console
Also, to properly autoload Symfony classes we’ll have to register Symfony namespace (assuming Zend_Loader_Autoloader
is used for autoloading).
Testing installation
Symfony Console itself has some basic commands. Let’s try running them. Create the file console
under scripts
directory, and make it executable.
[cli-show]$ mkdir scripts && touch scripts/console && chmod a+x scripts/console
This script will be the entry point for all console commands. We’ll use the default Symfony\Component\Console\Application
class provided by Symfony Console. Contents of our script:
This code is very similar to the code in index.php
and we should avoid duplicating it, but for now let’s just try it:
[cli-show]$ scripts/console
A nice looking output should appear, telling you possible command-line switches and commands.
Introducing Zend application
Right now CLI script doesn’t know anything about existing Zend application. In order to properly use business-logic of our application, we have into set correct application environment, instantiate instance of Zend_Application and bootstrap it. Also, we should move bootstrapping code to separate file and reuse it between our CLI script, index.php
and index-test.php
files. Considering all of this, let’s rewrite the script:
We need to require and configure Zend’s autoloader by hand, because our application isn’t yet bootstrapped at this point. Zend’s library should be in include path, otherwise we must manually add it using set_include_path
. We use Symfony\Component\Console\Input\ArgvInput
to get application’s environment from command-line. If it’s not passed, ‘development’ environment will be used. Note that we might want to save $zendApp
somewhere in order to reference to it in the future. I see 2 options:
- put it into
Zend_Registry
- create a subclass of
Symfony\Component\Console\Application
which will receive instance ofZend_Application
as a constructor argument
As you might see, we’ve moved bootstrapping code into separate bootstrapper.php
file under project’s root. It might look like this:
index.php
will be using it too:
Writing console commands
Every command is a subclass of Symfony\Component\Console\Command\Command
. In order to keep commands organized, we can add a new resource type called “command” by modifying Bootstrap class:
Now we could create application/commands
directory and add our commands there. For example, here is the Time command:
After creating command, we must add it to the list of known commands by calling addCommands
. This is true for all commands (Doctrine ORM, for instance, has many console commands):
Let’s see what time is it:
[cli-show]$ scripts/console app:time
Current time: 18:12:02
Use it
Symfony Console is a really great component. It’s decoupled, so you can use it in any kind of application. Even if you aren’t going to write your own commands, you can still use this approach to integrate any library which uses Symfony Console, such as Doctrine ORM. And if you’re on PHP>=5.3 and facing a problem of writing console task, you should definitely use it.