meritum/cli
Composer 安装命令:
composer require meritum/cli
包简介
Module-first console kernel (Sage) for the Meritum ecosystem
README 文档
README
Module-first console kernel (Sage) for the Meritum ecosystem. Wraps symfony/console with a clean bootstrapping API — constructor injection for dependencies, fluent builders for command definitions, and the same kernel lifecycle as meritum/http.
Requirements
- PHP 8.4+
- georgeff/kernel ^1.6
- symfony/console ^8.1
Installation
composer require meritum/cli
Bootstrapping
Create an entry point (e.g. bin/console):
#!/usr/bin/env php <?php require __DIR__ . '/../vendor/autoload.php'; use Georgeff\Kernel\Environment; use Meritum\Cli\CliKernel; $kernel = new CliKernel(Environment::Production); // register modules and commands here $kernel->boot(); exit($kernel->run());
Customising the application name and version
$kernel = new CliKernel(Environment::Production); $kernel->setName('myapp'); $kernel->setVersion('1.0.0');
These must be set before boot().
Registering Commands
Commands are registered via the kernel's container using the cli.commands tag. The CliKernelOption enum holds the tag name:
use Meritum\Cli\CliKernelOption; $kernel->define(CreateUserCommand::class, function ($c) { $command = new CreateUserCommand($c->get(UserRepository::class)); $command->setName('user:create') ->setDescription('Create a new user') ->addArgument('email')->description('The user email address') ->addOption('admin')->description('Grant admin privileges'); return $command; })->tag(CliKernelOption::CommandTag->value);
Commands are resolved from the container at dispatch time, so all dependencies are injected via the constructor.
Writing Commands
Extend Meritum\Cli\Command\Command and implement __invoke:
use Meritum\Cli\Command\Command; use Meritum\Cli\ExitCode; use Meritum\Cli\Output\SageStyleInterface; use Symfony\Component\Console\Input\InputInterface; final class CreateUserCommand extends Command { public function __construct(private readonly UserRepository $users) {} public function __invoke(InputInterface $input, SageStyleInterface $output): ExitCode { $email = $input->getArgument('email'); $this->users->create($email); $output->success("User {$email} created."); return ExitCode::Success; } }
The constructor is reserved for real dependencies. All command metadata (name, description, arguments, options) is configured in the factory definition.
Arguments
$command->addArgument('name'); // required by default $command->addArgument('name')->optional(); // optional $command->addArgument('name')->optional('default'); // optional with default $command->addArgument('tags')->array(); // required array $command->addArgument('tags')->array()->optional(); // optional array $command->addArgument('name') ->description('The target name') ->suggest('foo', 'bar'); // shell completion hints
Options
$command->addOption('force'); // boolean flag (--force) $command->addOption('output')->required(); // requires a value (--output=path) $command->addOption('output')->optional('/tmp'); // optional value with default $command->addOption('tag')->required()->array(); // repeatable (--tag=foo --tag=bar) $command->addOption('ansi')->negatable(); // --ansi / --no-ansi $command->addOption('output') ->shortcut('o') // -o shortcut ->description('Output path') ->suggest('/tmp', '/var/log'); // shell completion hints
Calling Commands from Commands
A command can invoke another command via call(). The kernel must be initialised (i.e. the command must be registered and the kernel booted) for this to work:
public function __invoke(InputInterface $input, SageStyleInterface $output): ExitCode { $this->call('cache:clear', $output); $this->call('cache:warm', $output, ['--env' => 'prod']); return ExitCode::Success; }
If no output is passed, the sub-command's output is discarded. The return value is the sub-command's exit code.
Exception Handling
Register an ExceptionHandlerInterface implementation to catch unhandled exceptions thrown during dispatch. Without one, exceptions propagate to the caller.
use Meritum\Cli\Exception\ExceptionHandlerInterface; use Meritum\Cli\Output\SageStyleInterface; use Symfony\Component\Console\Input\InputInterface; final class ConsoleExceptionHandler implements ExceptionHandlerInterface { public function handle(\Throwable $e, InputInterface $input, SageStyleInterface $output): void { $output->error($e->getMessage()); } }
Register it in the kernel before boot:
$kernel->define(ExceptionHandlerInterface::class, fn () => new ConsoleExceptionHandler())->share();
The kernel returns ExitCode::Error (1) when the exception handler is invoked.
Kernel Lifecycle
CliKernel follows the standard georgeff/kernel lifecycle:
$kernel->onBooting(function ($kernel) { /* before boot */ }); $kernel->onBooted(function ($kernel) { /* after boot */ }); $kernel->onShutdown(function ($kernel) { /* before shutdown */ });
handle() requires the kernel to be booted and not shutdown. run() calls handle() and must also be called on a live kernel.
Modules
Commands and services can be packaged into reusable modules:
use Georgeff\Kernel\KernelInterface; use Georgeff\Kernel\Module\ModuleInterface; use Meritum\Cli\CliKernelOption; final class MigrationsModule implements ModuleInterface { public function register(KernelInterface $kernel): void { $kernel->define(MigrateCommand::class, fn ($c) => (new MigrateCommand( $c->get(Database::class) ))->setName('migrate')->setDescription('Run pending migrations')) ->tag(CliKernelOption::CommandTag->value); } }
$kernel->addModule(new MigrationsModule());
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 3
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-13