henzeb / laravel-console-facade
与控制台交互的便捷 facade
Requires
- php: ^8.1
- illuminate/support: ^10|^11
Requires (Dev)
- nesbot/carbon: v2.72.2
- orchestra/testbench: ^v8.21.1|^9
- phpstan/phpstan: ^1.4
- phpunit/phpunit: ^9.6.6|^10
Suggests
- ext-pcntl: *
This package is auto-updated.
Last update: 2024-09-12 10:17:25 UTC
README
此包允许您从不在命令类内部的任何地方管理控制台输出。
由于我的应用程序要求逻辑不直接在命令类内部,我发现自己不得不在构造函数中添加输出,创建了丑陋且不可重用的代码。这简化了我的过程,现在也简化了您的过程。
安装
只需使用以下命令安装。
composer require henzeb/laravel-console-facade
用法
底层使用 InteractsWithIO
trait,因此您可以通过 facade 执行在命令内部可以执行的所有输出操作。
use Henzeb\Console\Facades\Console; class MyClass { public function writeMessage(): void { Console::ask('Would you like to be able to do this?'); Console::info('This message was brought to you by Henzeb'); } }
控制台助手
除了使用 Console facade,您还可以使用 console
助手方法。
use function Henzeb\Console\Functions\console; console('hello'); // outputs hello console()->info('hello'); // outputs hello console()->ask('Want an answer?'); // asks you a question
注意:在整个文档中使用了 facade,但一切都可以通过助手方法访问。
Laravel 组件工厂
Laravel 发布了他们命令的新样式,并为此使用了一个特殊的 Factory。使用此方法,您可以在自己的类中使用它们。
use Henzeb\Console\Facades\Console; class MyClass { public function writeMessage(): void { Console::components()->ask('Would you like to be able to do this?'); Console::components()->info('This message was brought to you by Henzeb'); Console::components()->bulletList(['this one', 'Another one']); } }
部分管理
该 facade 还允许您管理和使用部分。在部分内部,您只能使用 InteractsWithIO
中的输出方法,如 table
、progressbar
或 info
,这意味着不能执行提问。
use Henzeb\Console\Facades\Console; class MyClass { public function useSection(): void { Console::section()->table(['header'=>'title'], [[]]); Console::section('section2')->withProgressBar(100, fn()=>true); Console::section('section1')->components()->bulletList(['this one', 'Another one']); Console::section('section1')->clear(); Console::section('section3')->info('This message was brought to you by Henzeb'); } }
当您不传递名称时,每次调用部分时都会分配一个 uniqid
。您可以通过以下方式检索此部分的名称
$section = Console::section(); $section->name(); //returns string similar to 64350abe27355 $section = Console::section('section1'); $section->name(); //returns section1
延迟渲染
延迟渲染在您必须从头开始重建事物时非常有用,例如一个需要大量时间的表格。使用此方法,所有内容首先生成,然后再输出到控制台。
use Henzeb\Console\Facades\Console; use Henzeb\Console\Output\ConsoleSectionOutput; class MyClass { public function renderWhenReady(): void { Console::section()->render( function(ConsoleSectionOutput $section){ $section->table(['header'=>'title'], [[]]); } ); Console::section( 'section2', function(ConsoleSectionOutput $section){ $section->table(['header'=>'title'], [[]]); } ); } }
替换
当涉及到重复渲染时,Symfony 的默认 overwrite
方法有点慢。如果您发现您的控制台应用程序闪烁,replace
是一个好的选择。
注意:render
、watch
、tail
以及 section
上的回调方法都在底层使用 replace
。
监视
watch
是一个模仿 Linux 中 watch
命令的方法。默认情况下,它将每 2 秒执行一次给定的回调。
Console::watch( function (ConsoleSectionOutput $output) { $output->info(now()->toDateTimeString()); }, );
您也可以指定刷新率以加快或减慢循环。
Console::watch( function (ConsoleSectionOutput $output) { $output->info(now()->toDateTimeString()); }, 1 );
您还可以指定部分的名称。这样,您就可以在例如 trap
信号中操作部分。
Console::watch( function (ConsoleSectionOutput $output) { $output->info(now()->toDateTimeString()); }, sectionName: 'yourName' );
尾部
tail
可以用来“滚动”添加的行。就像 Linux 命令一样,tail
显示您最后 n
行。
Console::tail(); // returns a scrollable section with 10 lines Console::tail(5); // returns a scrollable section with 5 lines Console::tail(10, 'mySection'); // returns a scrollable mySection section Console::section('mySection')->tail(10); Console::section('mySection')->tail(10)->tail(5);//downgrades height to 5 Console::section('mySection')->setMaxHeight(10); // uses Symfony's implementation Console::tail()->setMaxHeight(15); // upgrades height to 15
在 Symfony 的 ConsoleSectionOutput 中已经存在这样做的方法,但存在许多问题。此实现修复了这些问题,并允许您轻松使用任何输出,如进度条和表格。
您仍然可以在常规部分中使用 Symfony 的实现。
退出
退出允许您在代码的任何地方调用退出,同时使其易于测试。
Console::exit(); Console::exit(1);
退出钩子
您还可以添加在调用 exit
时执行的钩子。请注意,它不会将它们注册为关闭函数。
Console::onExit( function(int $exitcode) { Console::info('exited with code '.$exitcode); } ); Console::onExit( function() { Console::info('exited with code 123'); }, 123 );
捕获
就像Laravel一样,有一个trap
方法来注册信号。在底层,这并不是使用Laravel和Symfony为向后兼容性而创建的逻辑,但它是相似的。更多信息请参见#43933。
在以下场景中,当给SIGINT
信号时,三个都会运行,当给SIGTERM
信号时,第二个也会运行。第一个处理程序返回true。这意味着在所有处理程序执行后,会给出一个退出信号。
Console::trap( function () { print('first handler'); return true; }, SIGINT ); Console::trap( function () { print('second handler'); var_dump(func_get_args()); return false; }, SIGINT, SIGTERM ); Console::trap( function () { print('third handler'); }, SIGINT );
重新捕获
trap允许你捕获新的信号处理程序。这在你想要能够连续按两次CTRL+C
时很有用。在下面的例子中,下次收到信号时,应用将强制退出。
Console::trap( function () { print('first handler'); Console::trap( function () { print('second handler'); return true; }, SIGINT ); }, SIGINT );
提示:当处理程序已经通过常规方式或通过Laravel的实现注册时,你可以使用pcntl_signal_get_handler
将其传递给trap
。
注意:这之前是onSignal
,但我已经废弃了这个方法,因为Laravel正在使用trap
。
取消捕获
和Laravel一样,有一个取消捕获的方法。这个方法会像Laravel实现那样自动调用,所以你可以在你的命令中使用Artisan::call
而不执行错误的信号处理程序。
Console::untrap();
合并选项和参数
在某些情况下,你可能想要合并选项或参数,比如恢复一个带有存储在缓存中的特定选项或参数的进程,或者重新配置一个正在运行的守护进程。
Console::mergeOptions(['env'=>'production']); Console::mergeArguments(['yourArgument'=>true]);
当选项或参数通过命令行设置时,该值将优先。
optionGiven和argumentGiven
在Laravel的Command
中,确定用户是否指定了选项或参数可能会变得相当混乱。具有可选参数的选项在设置或未设置时都返回null。当你设置默认值时,你可以弄清楚它,但这并不真正友好,感觉像是黑客式而非整洁的代码。
以下方法告诉你用户是否已将选项或参数添加到命令行
// artisan your:command --check --test=false Console::optionGiven('check'); // returns true Console::optionGiven('test'); // returns true Console::optionGiven('verify'); // returns false // artisan your:command verify Console::argumentGiven('check'); //returns false Console::argumentGiven('verify'); //returns true
验证
无论你构建的是将要分发的控制台应用,还是只想确保没有人能破坏你的应用,你都需要使用验证。Laravel控制台外观使得这变得非常容易。
假设你想要验证以下签名的输入
{id?} {--name=} {--age=*} {--birth=}
在configure
方法中,你只需定义以下内容
Console::validateWith( [ 'id' => 'bail|int|exists:users', '--name'=>'string|min:2', '--age.*' => 'bail|int|between:0,150', '--birth' => 'bail|prohibits:--age|date' ] );
当运行你的命令时,验证将自动执行。
在底层,这使用了Laravel的验证引擎,因此你可以使用验证引擎接受的任何内容。
注意事项:当你想要验证选项与可能未传递的参数或选项时,你可能需要编写自己的Rule
或闭包。
消息
由于翻译主要基于来自HTTP请求的输入,你可能想要给出不同的翻译。就像使用Laravel的验证引擎一样,添加一个第二个数组。
Console::validateWith( [ 'id' => 'bail|int|exists:users', '--name' => 'string|min:2', '--age.*' => 'bail|exclude_with:--birth|int|between:0,150', '--birth' => 'bail|prohibits:--age|date', ], [ 'exists' => 'User with given id does not exist!' 'prohibits' => 'Cannot be used together with :other' ] );
属性名称
Laravel允许你重命名属性。
Console::validateWith( [ 'id' => 'bail|int|exists:users', '--name' => 'string|min:2' ], attributes: [ 'id' => 'user id', '--name' => 'name' ] );
值名称
就像属性一样,你也可以给某些值命名。
下面我们看到了一个例子,其中接受的标志必须在指定任何性别时是true
的形式。
Console::validateWith( [ '--gender' =>'required|in:x,f,m', '--accepted' => 'accepted_if:--gender,x,--gender,f,--gender,m', ], valueNames: [ '--gender' => [ 'm' => 'male', 'f' => 'female', 'x' => 'other gender' ] ] );
在验证之前的回调
当你需要在执行之前访问Validator实例时,你可以使用beforeValidation
方法。
Console::beforeValidation( function(Illuminate\Validation\Validator $validator){ // your logic } );
基于闭包的命令
当运行用Artisan::command()
定义的ClosureCommands
时,它不会自动验证。相反,你可以做以下操作
Artisan::command( 'your:command {id?} {--name=} {--age=*} {--birth=}', function () { Console::validateWith( [ // ] ); Console::validate(); // } );
详细程度
控制台为你提供了在应用内部处理详细程度的易于使用的界面。
Console::verbose('verbose'); // only prints `verbose` when -v or higher is passed. Console::veryVerbose('very verbose'); // only prints `very verbose` when -vv or higher is passed. Console::debug('debug'); // only prints `debug` when -vvv is passed.
这些方法使用以下样式进行着色,如果您愿意,可以覆盖它们。
高级详细程度
除了简单的线条外,控制台还允许您使用任何可用的输出方法。
Console::verbose()->info('info'); // only prints `info` when -v or higher is passed. Console::debug()->ask('debug?'); // only asks when -vvv is passed, returns null otherwise Console::veryVerbose()->ask('very verbose?', 'no'); // only asks when -vv or higher is passed, returns 'no' otherwise Console::verbose()->withProgressbar(2, fn() => true); // only shows the progressbar when -v or higher is passed
注意:由于详细程度,进度条未显示,但给定的可调用函数仍然被执行。另外请注意,当详细程度不匹配时,监视将完全不会运行。
详细程度和部分
详细程度接口也支持部分。
Console::section('mySection')->debug('debug'); // only prints `debug` when -vvv is passed. Console::section('mySection')->debug()->info('info');// only prints `info` when -vvv is passed. Console::debug()->section('mySection')->info('info');// only prints `info` when -vvv is passed.
注意:请注意,详细部分与非详细部分相同。这意味着您不能只清除部分内的详细输出,因为这将会清除整个部分。
静音
静音是一个基于布尔值隐藏元素(如进度条)的方便方法。
Console::silence(false)->info('test'); // prints test Console::silence(true)->info('test'); // prints nothing Console::silence(false)->debug('test'); // prints test when -vvv is passed. Console::silence(true)->debug('test'); // prints nothing, even when -vvv is passed. Console::section('section')->silence(true)->info('test'); // prints nothing Console::section('section')->silence(false)->info('test'); // prints test Console::silence(true)->withProgressBar(5, fn()=>true); // runs the callback, but won't show progress Console::silence(false)->withProgressBar(5, fn()=>true); // runs the callback, and shows progress
您甚至可以链式静音,这样输出只有在提供参数组合时才会显示
Console::silence(false)->silence(false); // shows output Console::silence(true)->silence(false); // shows no output Console::silence(false)->silence(true); // shows no output Console::silence(true)->silence(true); // shows no output
取消静音
取消静音是静音
的直接对立面。
Console::unsilence(true)->info('test'); // prints test Console::unsilence(false)->info('test'); // prints nothing Console::unsilence(true)->debug('test'); // prints test when -vvv is passed. Console::unsilence(false)->debug('test'); // prints nothing, even when -vvv is passed. Console::section('section')->unsilence(false)->info('test'); // prints nothing Console::section('section')->unsilence(true)->info('test'); // prints test Console::unsilence(false)->withProgressBar(5, fn()=>true); // runs the callback, but won't show progress Console::unsilence(true)->withProgressBar(5, fn()=>true); // runs the callback, and shows progress
注意:您可以用静音
做的一切,都可以用取消静音
来做。您甚至可以在链式命令中混合它们。
宏
控制台外观和Henzeb\Console\Output\ConsoleSectionOutput
可以使用Laravel的Macroable特性进行宏操作。
Console::macro(...) Henzeb\Console\Output\ConsoleSectionOutput::macro(...)
请参阅文档
条件
您可以在外观以及内部部分中使用when
和unless
,就像您习惯的那样。请参阅文档
测试
除了常用的外观测试选项外,我还添加了一些方便的方法,用于在测试中使用。
Console::shouldExit(); Console::shouldNotExit(); Console::shouldExitWith(int $seconds); Console::shouldSleep(); Console::shouldNotSleep(); Console::shouldSleepWith(int $seconds); Console::watchShouldLoop(int $times, int $sleep = null);
测试此包
composer test
变更日志
请参阅变更日志以获取有关最近更改的更多信息。
贡献
请参阅贡献指南以获取详细信息。
安全
如果您发现任何与安全相关的问题,请通过电子邮件henzeberkheij@gmail.com联系,而不是使用问题跟踪器。
致谢
许可证
GNU AGPLv。请参阅许可证文件以获取更多信息。