大家好,我是小皮
kode/console 是一个专为现代 PHP 应用设计的通用控制台工具包,旨在为 kodephp 框架提供底层 CLI 支持,同时确保其完全独立于任何框架,可被 Laravel、Symfony、Slim、thinkphp8、webman、thinkphp6、自研框架无缝集成。
本包采用 PHP 8.1+ 的最新特性(如 readonly、enum、never、true 返回类型等),支持泛型协变/逆变,使用反射进行元数据提取但保证性能与安全,提供完整的类型提示与代码智能感知支持。
✅ 核心特性
- ✅ 命名简洁无冲突(避免与 PHP 原生函数/类重名)
- ✅ 支持协变 (covariance) 与逆变 (contravariance)
- ✅ 无全局副作用,不污染
$_SERVER 或 define - ✅ IDE 完整识别支持(通过 PHPStan 级别 12 + PHPDoc + Attributes)
- ✅ 支持未来扩展:协程、多线程、多进程(通过事件钩子预留接口)
🧩 架构设计
kode/console├── Command.php // 命令基类(包含所有增强功能)├── Kernel.php // 控制台内核,负责注册与调度(包含所有增强功能)├── Input.php // 输入解析器(argv)├── Output.php // 输出封装(支持颜色、格式)├── Signature.php // 命令签名解析器(DSL 风格)├── Event.php // 事件系统├── EventManager.php // 事件管理器├── CommandGroup.php // 命令分组├── Contract/ // 接口定义│ ├── IsCommand.php│ ├── IsInput.php│ ├── IsOutput.php│ ├── IsKernel.php│ ├── IsEvent.php│ ├── IsEventManager.php│ └── IsMiddleware.php├── Middleware/ // 中间件│ └── LoggingMiddleware.php├── Listener/ // 事件监听器│ └── CommandLogger.php└── Helper/ // 工具类(反射、类型推断等) └── Reflector.php
🧱 核心类与方法
1. Command 类
namespaceKode\Console;use Kode\Console\Contract\IsCommand;use Kode\Console\Input;use Kode\Console\Output;abstractclassCommandimplementsIsCommand{public readonly string $name; // 命令名,如 "app:serve"public readonly string $desc; // 描述public readonly string $usage; // 用法说明/** * @var string[] */protectedarray $aliases = [];/** * @var array<array{example: string, description: string}> */protectedarray $examples = [];/** * @var string[] */protectedarray $related = [];protected ?string $group = null;/** * 执行命令 */abstractpublicfunctionfire(Input $in, Output $out): int;/** * 注册命令签名 */publicfunctionsig(string $def): static{ /* ... */ }/** * 设置描述 */publicfunctionabout(string $text): static{ /* ... */ }/** * 设置命令别名 */publicfunctionalias(string|array $alias): static;/** * 添加使用示例 */publicfunctionexample(string $example, string $description = ''): static;/** * 设置相关命令 */publicfunctionrelated(string|array $commands): static;/** * 设置命令组 */publicfunctiongroup(string $group): static;/** * 显示详细帮助信息 */publicfunctionshowHelp(Input $in, Output $out): void;}
🔹 命名理由:fire() 比 handle() 更短且无 Laravel 冲突;sig() 是 signature 的极简缩写,易记。
2. Kernel 控制台内核
namespaceKode\Console;classKernel{/** * @var Command[] 协变支持 */privatearray $cmds = [];/** * @var array<string, CommandGroup> */privatearray $groups = [];/** * @var IsMiddleware[] */privatearray $middlewares = [];private ?IsEventManager $eventManager = null;/** * @var array<string, string> */privatearray $aliases = [];/** * 注册命令 * * @param class-string<Command> $cls */publicfunctionadd(string $cls): static;/** * 添加命令别名 */publicfunctionalias(string $alias, string $commandName): static;/** * 添加命令组 */publicfunctionaddGroup(CommandGroup $group): static;/** * 添加中间件 */publicfunctionaddMiddleware(IsMiddleware $middleware): static;/** * 设置事件管理器 */publicfunctionsetEventManager(IsEventManager $eventManager): static;/** * 运行控制台 */publicfunctionboot(array $argv): int;/** * 获取所有命令(逆变输入) * * @return iterable<Command> */publicfunctionall(): iterable;}
3. Input 输入解析器
namespaceKode\Console;classInput{publicfunctionarg(string $key, mixed $default = null): mixed;publicfunctionhas(string $key): bool;publicfunctionflag(string $name): bool; // --verbosepublicfunctionopt(string $name): mixed; // --port=8080publicfunctionraw(): array; // 原始 argv// 交互式输入功能publicstaticfunctionask(string $question, string $default = ''): string;publicstaticfunctionconfirm(string $question, bool $default = false): bool;publicstaticfunctionchoice(string $question, array $choices, string|int|null $default = null): string|int|null;}
🔹 方法名极简:arg, flag, opt —— 无歧义、易记、无 PHP 冲突
4. Output 输出封装
namespaceKode\Console;classOutput{publicfunctionline(string $text, string $color = ''): void;publicfunctioninfo(string $msg): void;publicfunctionwarn(string $msg): void;publicfunctionerror(string $msg): void;publicfunctionsuccess(string $msg): void;publicfunctionraw(string $text): void;// 增强功能publicfunctionstyled(string $text, string $style = 'info'): void;publicfunctiontable(array $headers, array $rows): void;publicfunctionprogress(int $current, int $total, int $width = 50): void;publicfunctionjson(mixed $data): void;}
🔹 颜色支持 ANSI 与自动检测 TTY
5. Signature 命令签名 DSL
// 示例:serve --host=localhost --port=8080 {app?}$sig = new Signature('serve {app?} {--host=} {--port=8080} {--secure}');// 解析后生成元数据,用于 Input 验证
🚀 未来扩展性设计
| |
|---|
| fire() |
| Kernel |
| 通过 pthreads 或 parallel 扩展(非内置,但不阻止) |
| Kernel 触发 before:run, after:exit |
⚠️ 本包不内置协程/多线程,但不阻碍上层框架实现
📦 Composer 安装
composer require kode/console
🚀 快速开始
综合使用示例
下面是一个综合性的使用示例,展示了如何创建一个功能完整的控制台应用,包含了命令定义、事件系统、中间件、交互式输入和增强输出等功能:
<?phpuse Kode\Console\Command;use Kode\Console\Input;use Kode\Console\Output;classDemoCommandextendsCommand{publicfunction__construct(){parent::__construct('demo', 'A demo command showcasing various features', 'demo {name?} {--upper} {--repeat=1} {--interactive}' );$this->sig($this->usage);// 添加别名$this->alias(['d', 'demo:run']);// 添加使用示例$this->example('demo John --upper', 'Greet John in uppercase');$this->example('demo Jane --repeat=3', 'Greet Jane 3 times');$this->example('demo --interactive', 'Run in interactive mode');// 设置相关命令$this->related(['hello', 'serve']);// 设置命令组$this->group('examples'); }publicfunctionfire(Input $in, Output $out): int{// 显示帮助信息if ($in->flag('help')) {$this->showHelp($in, $out);return0; }// 交互式模式if ($in->flag('interactive')) {return$this->runInteractive($in, $out); }// 获取参数和选项 $name = $in->arg('name', 'World'); $upper = $in->flag('upper'); $repeat = (int) $in->opt('repeat', 1);// 处理问候语 $greeting = "Hello, {$name}!";if ($upper) { $greeting = strtoupper($greeting); }// 输出问候语for ($i = 0; $i < $repeat; $i++) { $out->line($greeting); }// 展示增强输出功能 $out->success("Command executed successfully!");// 表格输出示例 $out->info("User Information:"); $headers = ['Name', 'Role', 'Status']; $rows = [ [$name, 'User', 'Active'], ['System', 'Admin', 'Online'] ]; $out->table($headers, $rows);// JSON输出示例 $data = ['command' => 'demo','name' => $name,'upper' => $upper,'repeat' => $repeat ]; $out->json($data);return0; }privatefunctionrunInteractive(Input $in, Output $out): int{// 询问用户输入 $name = $in->ask('What is your name?', 'Anonymous');// 确认操作if (!$in->confirm("Hello, {$name}! Do you want to continue?", true)) { $out->line('Goodbye!');return0; }// 选择选项 $choices = ['1' => 'Basic greeting','2' => 'Uppercase greeting','3' => 'Repeat greeting' ]; $selected = $in->choice('Please select a greeting style:', $choices, '1');switch ($selected) {case'1': $out->line("Hello, {$name}!");break;case'2': $out->line("HELLO, {$name}!");break;case'3': $repeat = (int) $in->ask('How many times should I repeat?', '3');for ($i = 0; $i < $repeat; $i++) { $out->line("Hello, {$name}!"); }break; }return0; }}
- 创建控制台应用入口文件(console.php):
<?phprequire__DIR__ . '/vendor/autoload.php';use Kode\Console\Kernel;use Kode\Console\Middleware\LoggingMiddleware;use Kode\Console\EventManager;use Kode\Console\Listener\CommandLogger;// 创建内核实例$kernel = new Kernel();// 设置事件管理器$eventManager = new EventManager();$kernel->setEventManager($eventManager);// 添加事件监听器$logger = new CommandLogger();$eventManager->listen('command.executing', [$logger, 'handle']);$eventManager->listen('command.executed', [$logger, 'handle']);// 添加中间件$kernel->addMiddleware(new LoggingMiddleware());// 注册命令$kernel->add(DemoCommand::class);// 添加命令别名$kernel->alias('d', 'demo');// 运行控制台应用exit($kernel->boot($argv));
# 基础用法php console.php demo# 输出: Hello, World!# 带参数php console.php demo John# 输出: Hello, John!# 使用选项php console.php demo Jane --upper --repeat=3# 输出: HELLO, Jane! (重复3次)# 交互式模式php console.php demo --interactive# 查看帮助php console.php demo --help
📚 总结
| |
|---|
| 包名 | kode/console |
| PHP 版本 | |
| 命名风格 | 简洁、无冲突(fire, sig, in, out) |
| 类型安全 | |
| 反射安全 | |
| IDE 支持 | Trea / PHPStorm / VSCode 完整识别 |
| 框架兼容 | |
| 未来扩展 | |
感谢大家阅读,个人观点仅供参考,欢迎在评论区发表不同观点。
欢迎关注、分享、点赞、收藏、在看,我是微信公众号「PHP驿站」作者小皮。