Usage Guide
This page covers the basic usage of this toolkit, just like a step-by-step guide. If you've never used SmartConsole before, you've come to the right place. If you are looking for a fully detailled listing of features instead, head on to the References.
Installation¶
Require the toolkit via composer:
$ composer require mcstreetguy/smart-console
Basic Setup¶
To get started with SmartConsole we need to do some basic configuration (yes, we can't completely avoid this step) and tell our application what it's called, which version it's on and - especially - what commands are available. There are several ways to achieve this but for now we'll just stick to the best practices to keep it short and simple.
Developers Note
In exceptional cases it may happen that this approach does not fit your project setup. In this case you should of course choose a different solution. On the examples page you will find several alternatives but it is strongly discouraged to use them prematurely.
App Configuration¶
To do so, we simply create a class that inherits from the base class MCStreetguy\SmartConsole\Console
:
<?php namespace Vendor\MyCLI; use MCStreetguy\SmartConsole\Console; class MyApplication extends Console { protected function configure() { parent::configure(); $this->init([ 'name' => 'my-application', 'version' => '0.0.0-alpha', 'displayName' => 'My Application' ]); } }
Just by looking at the code example, it should be clear what happens. The configure method is called automatically on instantiation, so this is normally the place where we define our settings.
Developers Note
Since there are also configure-methods in the parent classes of our CLI that are required for the application to work properly you need to ensure that parent::configure()
is called before you start with your own config!
Developers Note
The init
method is obviously not the only configuration method available on the class but it is recommended to use it with an config array as this ensures bugless execution as far as possible.
If you prefer to, you can also set the values directly but in this case you have to keep a closer eye on your code.
To say a few more words about the above example:
name
is obviously the actual name of our application. Typically this is the same as the binary file name we later want to execute.version
defines the version of our application. This can be any semantic version string.displayName
is the readable form of thename
property. This is used e.g. on the help page.
There are a few more options available but for now this suffice. We got barely 20 lines of code and that's all we have to do with configuration. In fact, we'll have to come back to this file to define our commands, but we'll deal with that later.
The executable¶
Before we get to the really exciting part, we should create a binary. Like the other components of SmartConsole, this isn't much work and has the advantage that we can test the commands we are about to create directly.
#!/usr/bin/env php <?php if (file_exists($autoload = __DIR__.'/../../../autoload.php')) { require_once $autoload; } else { require_once __DIR__.'/../vendor/autoload.php'; } Vendor\MyCLI\MyApplication::run();
The complex if-condition at the beginning of our code loads the composer autoload file.
It assumes that you place your binary in a subfolder of your project root (such as bin/
).
The else branch is used to require the autoloader if the package got installed in another project below the vendor/
folder.
The last line then executes our previously configured application. You can verify that everything works as expected by executing the binary. It should show up a help page describing all possible commands and options (the default ones currently):
My Application version 0.0.0-alpha USAGE my-application [-h] [-q] [-v [<level>]] [-V] [--ansi] [--no-ansi] [-n] <command> [<arg1>] ... [<argN>] ARGUMENTS <command> The command to execute <arg> The arguments of the command GLOBAL OPTIONS -h (--help) Display help about the command -q (--quiet) Do not output any message -v (--verbose) Increase the verbosity of messages: "-v" for normal output, "-vv" for more verbose output and "-vvv" for debug -V (--version) Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n (--no-interaction) Do not ask any interactive question AVAILABLE COMMANDS help Display the manual of a command
As you can see it is almost too easy to write a console application with SmartConsole. Even though the CLI can't do anything meaningful currently, at least it's working already.
Our first command¶
Now that we have everything up and running we can start adding commands to our application. This is done by creating command handler classes and telling the CLI about these.
So, one by one:
<?php namespace Vendor\MyCLI\Command; use MCStreetguy\SmartConsole\Command\AbstractCommand; /** * Print 'Hello World!' to the terminal. */ class HelloWorldCommand extends AbstractCommand { public function indexAction() { $this->io->out('Hello World!'); } }
We just created a command named 'hello-world' that prints out 'Hello World!' on execution.
(Yeah, I know, not very inventive, but it's enough for a demonstration)
You have to follow some guidelines so that SmartConsole recognizes everything correctly.
For example, the class name of a command handler must end in Command
and all relevant methods must end in Action
.
Relevant in this context means methods that represent either the sole or different functions of the command.
I'll explain the exact procedure of the algorithm later.
Now we extend our app config to tell it about our new command:
<?php namespace Vendor\MyCLI; use MCStreetguy\SmartConsole\Console; use Vendor\MyCLI\Commands\HelloWorldCommand; class MyApplication extends Console { protected function configure() { parent::configure(); $this->init([ 'name' => 'my-application', 'version' => '0.0.0-alpha', 'displayName' => 'My Application', 'commands' => [ HelloWorldCommand::class ] ]); } }
Let's have a look at the help page again to check for the freshly created command:
$ ./bin/my-application help
My Application version 0.0.0-alpha
USAGE
my-application [-h] [-q] [-v [<level>]] [-V] [--ansi] [--no-ansi] [-n] <command> [<arg1>] ... [<argN>]
ARGUMENTS
<command> The command to execute
<arg> The arguments of the command
GLOBAL OPTIONS
-h (--help) Display help about the command
-q (--quiet) Do not output any message
-v (--verbose) Increase the verbosity of messages: "-v" for normal output, "-vv" for more verbose output and "-vvv" for debug
-V (--version) Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n (--no-interaction) Do not ask any interactive question
AVAILABLE COMMANDS
hello-world Print 'Hello World!' to the terminal.
help Display the manual of a command
$ ./bin/my-application help hello-world USAGE my-application hello-world GLOBAL OPTIONS -h (--help) Display help about the command -q (--quiet) Do not output any message -v (--verbose) Increase the verbosity of messages: "-v" for normal output, "-vv" for more verbose output and "-vvv" for debug -V (--version) Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n (--no-interaction) Do not ask any interactive question
Wow, that was easy huh? Like this you define all your commands, their options, arguments and help-texts. Even very complex commands do not require any more configuration than you've already written. Speaking of which, let's implement a more complicated command right now.
A more complex command¶
Whereas 'complex' means that our command should have several sub-commands available.
Imagine this as with the Git CLI, where we sometimes have to type several command names one after the other.
For example the git remote
command has the sub-commands add
, remove
, show
and so on.
Let us take this example seriously and put it into practice. As you can imagine our command handler now looks a lot more complex. Every action method must now have a doc block and annotations have been added. Let's take a look at the code first and then at the help page to see what happens before I explain exactly what we do.
<?php namespace Vendor\MyCLI\Command; use MCStreetguy\SmartConsole\Annotations as CLI; use MCStreetguy\SmartConsole\Command\AbstractCommand; /** * Manage set of tracked repositories. */ class RemoteCommand extends AbstractCommand { /** * Adds a remote named <name> for the repository at <url>. * * The command git fetch <name> can then be used to create and update remote-tracking branches <name>/<branch>. * * @param string $name The name of the remote to add. * @param string $url The url of the remote to add. * @param bool $fetch Run git fetch <name> immediately after the remote information is set up. * @CLI\ShortName(option="fetch",short="f") */ public function addAction(string $name, string $url, bool $fetch = false) { // some logic } /** * Remove the remote named <name>. * * All remote-tracking branches and configuration settings for the remote are removed. * * @param string $name The name of the remote to remove. */ public function removeAction(string $name) { // some logic } /** * Gives some information about the remote <name>. * * @param string $name The name of the remote to display. */ public function showAction(string $name) { // some logic } /** * Show a list of existing remotes. * * @CLI\DefaultCommand */ public function listAction() { // some logic } }
$ ./bin/my-application help
My Application version 0.0.0-alpha
USAGE
my-application [-h] [-q] [-v [<level>]] [-V] [--ansi] [--no-ansi] [-n] <command> [<arg1>] ... [<argN>]
ARGUMENTS
<command> The command to execute
<arg> The arguments of the command
GLOBAL OPTIONS
-h (--help) Display help about the command
-q (--quiet) Do not output any message
-v (--verbose) Increase the verbosity of messages: "-v" for normal output, "-vv" for more verbose output and "-vvv" for debug
-V (--version) Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n (--no-interaction) Do not ask any interactive question
AVAILABLE COMMANDS
hello-world Print 'Hello World!' to the terminal.
help Display the manual of a command
remote Manage set of tracked repositories.
$ ./bin/my-application help remote USAGE my-application remote or: my-application remote add [-f] <name> <url> or: my-application remote remove <name> or: my-application remote show <name> or: my-application remote list COMMANDS add Adds a remote named <name> for the repository at <url>. The command git fetch <name> can then be used to create and update remote-tracking branches <name>/<branch>. <name> The name of the remote to add. <url> The url of the remote to add. -f (--fetch) Run git fetch <name> immediately after the remote information is set up. list Show a list of existing remotes. remove Remove the remote named <name>. All remote-tracking branches and configuration settings for the remote are removed. <name> The name of the remote to remove. show Gives some information about the remote <name>. <name> The name of the remote to display. GLOBAL OPTIONS -h (--help) Display help about the command -q (--quiet) Do not output any message -v (--verbose) Increase the verbosity of messages: "-v" for normal output, "-vv" for more verbose output and "-vvv" for debug -V (--version) Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n (--no-interaction) Do not ask any interactive question
As you can see, SmartConsole reads all of our doc-blocks and creates the respective sub-commands.
The parameters of our methods are also analysed and turned into arguments for required ones and into options for optional params.
In addition we define a short name for our fetch
option as well as a default command, which means the sub-command beeing executed when no sub-command name is given.
Developers Note
This annotation is actually required for a complex command to work properly. Leaving it out or specifying it twice or even more often leads to exceptions!