In this article, we're going to explore how you could create custom command-line interface (CLI) commands in your PHP applications using the Symfony Console component. After installing the necessary libraries, we'll create a few handful of examples to demonstrate the concepts of the Console component.
In fact, this component is used by several PHP frameworks to develop CLI applications, and a few popular frameworks are already using this component as a starting point.
What Is the Console Component?
The Symfony Console component allows you to create custom CLI commands in your PHP applications. If you have ever worked with Laravel or Symfony, you might be aware of the CLI tools they provide in order to ease day-to-day operations like:
- generating scaffolding code
- clearing caches
- installing, enabling and disabling add-on services
- running database migrations
- and more
In the case of Laravel, for example, it comes with the artisan
tool which provides plenty of utility commands that make our life easier. You may be surprised to know that the artisan
tool is built on top of the Symfony Console component itself! In fact, there are many frameworks that leverage the Console component to build their command-line tools.
In this article, we're going to explore the basics of the Console component so that you can create custom CLI commands in your PHP applications. To start with, we'll go ahead and install the Console component using Composer. After installation, we'll build a few examples for demonstration purposes.
Installation and Configuration
In this section, we're going to install the Console component that is required in order to create CLI commands in your PHP applications. I assume that you've installed Composer in your system—we'll need it to install the Console component which is available from Packagist.
Once you've installed Composer, go ahead and install the Console component using the following command.
$composer require symfony/console
That should have created the composer.json file, which should look like this:
{ "require": { "symfony/console": "^4.0" } }
Let's modify the composer.json file to look like the following one:
{ "require": { "symfony/console": "^4.0" }, "autoload": { "psr-4": { "Console\\": "src" }, "classmap": ["src"] } }
As we've added a new classmap
entry, let's go ahead and update the Composer autoloader by running the following command.
$composer dump -o
Now, you can use the Console
namespace to autoload classes under the src directory.
Your First HelloWorld Command
Creating CLI commands using the Console component is a two-step process.
- First, you need to create a console application which loads the necessary dependencies and registers your custom commands.
- Next, you need to create files for all commands that you have registered with the console application.
Create the Console Application
In this section, we'll go ahead and create our custom console application.
The proposed directory structure of our console application looks like this.
|-- bin | `-- console |-- composer.json |-- composer.lock |-- src | `-- App | `-- Commands | |-- ClearcacheCommand.php | `-- HelloworldCommand.php `-- vendor
Go ahead and create the main application file bin/console with the following contents. Please note that there's no file extension, and also make sure that it's executable as well since we'll need to run it from the command line.
#!/usr/bin/env php <?php require_once __DIR__ . '/../vendor/autoload.php'; use Symfony\Component\Console\Application; $app = new Application(); $app->run();
The first line in the file #!/usr/bin/env php
makes sure that it's run under the PHP environment. Go ahead and try to run it and see how it goes.
$bin/console 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
Not bad! With just a few lines of code, you have a custom console application rolling at your disposal! But it's not doing anything useful at the moment. In the next section, we'll see how you can create custom commands and register it with our custom console application.
Create the Hello World Command File
Let's go ahead and create our first custom command: HelloworldCommand
. Create the src/App/Commands/HelloworldCommand.php file with the following contents.
<?php namespace Console\App\Commands; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; class HelloworldCommand extends Command { protected function configure() { $this->setName('hello-world') ->setDescription('Prints Hello-World!') ->setHelp('Demonstration of custom commands created by Symfony Console component.') ->addArgument('username', InputArgument::REQUIRED, 'Pass the username.'); } protected function execute(InputInterface $input, OutputInterface $output) { $output->writeln(sprintf('Hello World!, %s', $input->getArgument('username'))); } }
There are two main methods that you should create while creating your custom command: configure
and execute
.
As the name suggests, the configure
method allows you to configure your command so that you can set up the command name, a short description of the command, help text, and more. You can also configure arguments for your command if you want to pass parameters while running a command.
In the above example, the command name is set to hello-world
. Also, we want to pass a username as the first argument, and hence we've configured it using the addArgument
method.
On the other hand, the execute
method contains the application logic of the command. In our case, we've kept it pretty simple by displaying Hello World as the output of the command.
Before you can go ahead and actually run this command, you need to register it with the console application which we've created in the previous section. Let's quickly revise the bin/console file to look like the following one.
#!/usr/bin/env php <?php require_once __DIR__ . '/../vendor/autoload.php'; use Symfony\Component\Console\Application; use Console\App\Commands\HelloworldCommand; $app = new Application(); $app->add(new HelloworldCommand()); $app->run();
As you can see, we've used the add
method of the Application
object to add the HelloworldCommand
command. Let's quickly list all the available commands.
$bin/console list 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: hello-world Prints Hello-World! help Displays help for a command list Lists commands
As expected, the hello-world
command appears in the list of available commands! Go ahead and run it!
$bin/console hello-world tutsplus Hello World!, tutsplus
So that's how you can set up basic commands!
A Real-World Example—Clear Cache Command
In the previous section, we built the hello-world
command to demonstrate the concepts of the Console component. In this section, we'll go ahead and create a real-world example which demonstrates how you could build a command to clear caches in your application.
Create the Clear Cache Command File
Go ahead and create the src/App/Commands/ClearcacheCommand.php file with the following contents.
<?php namespace Console\App\Commands; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; class ClearcacheCommand extends Command { protected function configure() { $this->setName('clear-cache') ->setDescription('Clears the application cache.') ->setHelp('Allows you to delete the application cache. Pass the --groups parameter to clear caches of specific groups.') ->addOption( 'groups', 'g', InputOption::VALUE_OPTIONAL, 'Pass the comma separated group names if you don\'t want to clear all caches.', '' ); } protected function execute(InputInterface $input, OutputInterface $output) { $output->writeln('Cache is about to cleared...'); if ($input->getOption('groups')) { $groups = explode(",", $input->getOption('groups')); if (is_array($groups) && count($groups)) { foreach ($groups as $group) { $output->writeln(sprintf('%s cache is cleared', $group)); } } } else { $output->writeln('All caches are cleared.'); } $output->writeln('Complete.'); } }
The configure
method is pretty much the same, except that we've used the addOption
method to add an option to our command. Thus, you could pass group values by using the --groups
parameter.
On the other hand, the execute
method contains the application logic of our command.
If you want to clear the cache of specific groups, you need to pass group names along with the --group
parameter. On the other hand, skip the --group
parameter if you want to clear all caches. You may have noticed that we've kept the --group
parameter optional by providing the InputOption::VALUE_OPTIONAL
value in the third argument of the addOption
method.
Registration and Testing With the Console Application
Before we go ahead and actually run it, let's register the command with our console application.
#!/usr/bin/env php <?php require_once __DIR__ . '/../vendor/autoload.php'; use Symfony\Component\Console\Application; use Console\App\Commands\HelloworldCommand; use Console\App\Commands\ClearcacheCommand; $app = new Application(); $app->add(new HelloworldCommand()); $app->add(new ClearcacheCommand()); $app->run();
Now, go ahead and run the bin/console clear-cache
command to clear all caches!
$bin/console clear-cache Cache is about to cleared... All caches are cleared. Complete.
Next, if you want to clear specific caches, you could try something like this.
$bin/console clear-cache --groups=group1,group2 Cache is about to cleared... group1 cache is cleared group2 cache is cleared Complete.
Of course, you will need to implement the actual logic to clear caches, but that should serve as a good starting point.
Conclusion
Today, we went through one of the popular components provided by the Symfony framework: the Console Component. It's really a useful component should you wish to develop your own CLI application which helps you execute your day-to-day utility tasks with ease.
In the first half, we went through the installation and configuration of the component. Then, in the second half, we created a couple of examples of console commands.
Let us know what you think in the comments below.
No comments:
Post a Comment