Application
The Application class is the main entry point for your CLI application. It handles command registration, input parsing, and command execution.
Class Definition
namespace Yalla;
class Application
{
private string $name;
private string $version;
private CommandRegistry $registry;
private Output $output;
private InputParser $input;
}Constructor
public function __construct(string $name = 'Yalla CLI', string $version = '1.0.0')Creates a new Application instance.
Parameters
$name(string): The name of your CLI application$version(string): The version of your CLI application
Example
$app = new Application('My CLI', '2.0.0');Methods
register()
public function register($command): selfRegisters a command with the application.
Parameters
$command(Command): The command instance to register
Returns
self: The Application instance for method chaining
Example
$app->register(new DeployCommand())
->register(new BackupCommand())
->register(new MigrateCommand());run()
public function run(): intRuns the application by parsing input and executing the appropriate command.
Returns
int: Exit code (0 for success, non-zero for errors)
Example
$exitCode = $app->run();
exit($exitCode);getName()
public function getName(): stringReturns the application name.
Returns
string: The application name
getVersion()
public function getVersion(): stringReturns the application version.
Returns
string: The application version
Default Commands
The Application automatically registers these built-in commands:
help- Show help for a commandlist- List all available commandscreate:command- Generate a new command classrepl- Start an interactive REPL sessioninit:repl- Create REPL configuration fileinit- Initialize a new CLI project
Complete Example
#!/usr/bin/env php
<?php
require 'vendor/autoload.php';
use Yalla\Application;
use App\Commands\DeployCommand;
use App\Commands\BackupCommand;
use App\Commands\TestCommand;
// Create application
$app = new Application('DevOps CLI', '1.5.0');
// Register custom commands
$app->register(new DeployCommand())
->register(new BackupCommand())
->register(new TestCommand());
// Run application
$exitCode = $app->run();
// Exit with appropriate code
exit($exitCode);Error Handling
The Application class handles errors gracefully:
try {
$app->run();
} catch (\Exception $e) {
// Errors are caught and displayed
// Exit code 1 is returned
}Command Not Found
When a command is not found:
Command 'unknown' not found.Exit code: 1
Missing Arguments
When required arguments are missing, the command should handle validation:
public function execute(array $input, Output $output): int
{
$file = $this->getArgument($input, 'file');
if (!$file) {
$output->error('File argument is required');
return 1;
}
// Continue...
return 0;
}Input Handling
The Application uses InputParser to parse command-line arguments:
./cli command arg1 arg2 --option=value -fParsed as:
[
'command' => 'command',
'arguments' => ['arg1', 'arg2'],
'options' => [
'option' => 'value',
'f' => true
]
]Default Behavior
When no command is specified, the list command is executed:
./cli
# Equivalent to: ./cli listExtending Application
You can extend the Application class for custom behavior:
class MyApplication extends Application
{
protected function registerDefaultCommands(): void
{
parent::registerDefaultCommands();
// Add your default commands
$this->registry->register(new CustomDefaultCommand());
}
public function run(): int
{
// Custom pre-run logic
$this->output->writeln($this->getBanner());
// Run application
return parent::run();
}
private function getBanner(): string
{
return <<<BANNER
╔═══════════════════════════╗
║ {$this->getName()} v{$this->getVersion()} ║
╚═══════════════════════════╝
BANNER;
}
}Testing
Testing an Application:
test('application runs command', function () {
$app = new Application('Test', '1.0');
$app->register(new TestCommand());
$_SERVER['argv'] = ['cli', 'test', 'arg'];
$result = $app->run();
expect($result)->toBe(0);
});Environment Variables
The Application respects these environment variables:
NO_COLOR- Disable colored outputTERM- Terminal type for color support detection
Thread Safety
The Application class is not thread-safe. Each thread should have its own Application instance.
Performance Considerations
- Commands are lazy-loaded when accessed
- The registry uses a hash map for O(1) command lookup
- Input parsing is done once per run
See Also
- Command - Base command class
- CommandRegistry - Command registration and management
- Output - Output formatting
- InputParser - Input parsing