den1008 / progress-status
计算进度
Requires
- php: >=7.0
- ext-mbstring: *
Requires (Dev)
- phpunit/phpunit: ~6.0 || ~7.0 || ~8.0 || ~9.0
README
ProgressStatus 是一个用于计算多模块程序总体执行进度的简单易用的组件,适用于 PHP。
安装
$ composer require den1008/progress-status
使用
主要元素是 StatusProcessor,它实现了计算进度的功能,需要传递处理程序,具体取决于需要将进度信息输出到何处。目前有两个处理程序:StdOutStatus 和 FileStatus,但您可以编写自己的类似处理程序。
StatusProcessor
为了通知用户进度变化,有两种方法:say() 或 sayStage()
$status->say(); //Вывод сообщений об изменении прогресса $status->sayStage(); //Вывод сообщений об изменении этапа выполнения
注意!所有处理程序都必须实现接口 IStatusHandler(方法 sayStageConcrete() 和 sayConcrete(),而不是方法 sayStage() 和 say())。这是为了能够筛选处理程序的消息。示例
$processor = new StatusProcessor([new SomeStatusHandler()]); $processor->setTotal(100) ->setStepProcessingProgress(25); //Теперь все хэндлеры будут получать сообщения с шагом 25% for ($i = 0; $i < 100; $i++){ $processor->increaseProgress()->say('processing'); }
输出 SomeStatusHandler
[I completed 25%] processing [I completed 50%] processing [I completed 75%] processing [I completed 100%] processing
使用 wrapSubProgram(Closure $func, $endProgress) 方法在嵌套子程序中计算统计数据,其中 $func 是要执行的子程序,而 $endProgress 是子程序完成时要达到的进度。示例使用
$processor = new StatusProcessor([new SomeStatusHandler()]); //Необходимо обязательно задавать общее количество, иначе будет выброшено исключение. //$processor->getNested() == 1 глубина вложенности $processor->setTotal(1000); //{%total%} = 1000 for ($i = 0; $i <= 20; $i += 10) { $processor->setProgress($i * 10); //$i=0 --> {%percent%} = 0%, {%progress%} = 0, {%commonPercent%} = 0% //$i=10 --> {%percent%} = 10%, {%progress%} = 100, {%commonPercent%} = 10% //$i=20 --> {%percent%} = 20%, {%progress%} = 200, {%commonPercent%} = 20% $processor->say('Процесс 1 {%percent%}% элементов ({%progress%} из {%total%})'); } //Запуск подпрограммы $processor->wrapSubProgram(function (StatusProcessor $processor){ //$processor->getNested() == 2 глубина вложенности //Подпрограмма ничего не знает о родительском статусе выполнения, поэтому ведет собственный расчет от 0 до {%total%} //Если не указать общее количество, процент выполнения будет равен 100%. $processor->setTotal(50); //{%total%} = 50 for ($i = 0; $i < 5; $i++) { $processor->increaseProgress(10); //$i=0 --> {%percent%} = 20%, {%progress%} = 10, {%commonPercent%} = 28% //$i=1 --> {%percent%} = 40%, {%progress%} = 20, {%commonPercent%} = 36% //$i=2 --> {%percent%} = 60%, {%progress%} = 30, {%commonPercent%} = 44% //$i=3 --> {%percent%} = 80%, {%progress%} = 40, {%commonPercent%} = 52% //$i=4 --> {%percent%} = 100%, {%progress%} = 50, {%commonPercent%} = 60% //Здесь параметры {%progress%} из {%total%} будут для текущего контекста, но {%commonPercent%}% - для общего $processor->say('Процесс 2 {%commonPercent%}% элементов ({%progress%} из {%total%})'); } }, 600); //Здесь 600 - прогресс который будет достигнут после выполнения подпрограммы //$processor->getNested() == 1 глубина вложенности //{%commonPercent%} == {%percent%} == 60%, т.к. ни одна подпрограмма не была обернута //{%progress%} = 600 //{%total%} = 1000 for ($i = 60; $i <= 100; $i += 10) { $processor->setProgress($i * 10); //$i=60 --> {%percent%} = 60% {%progress%} = 600, {%commonPercent%} = 60% //$i=70 --> {%percent%} = 70% {%progress%} = 700, {%commonPercent%} = 70% //$i=80 --> {%percent%} = 80% {%progress%} = 800, {%commonPercent%} = 80% //$i=90 --> {%percent%} = 90% {%progress%} = 900, {%commonPercent%} = 90% //$i=100 --> {%percent%} = 100% {%progress%} = 1000, {%commonPercent%} = 100% $processor->say('Процесс 1 {%percent%}% элементов ({%progress%} из {%total%})'); }
StdOutStatusHandler
该组件将进度信息输出到 std。简单的使用示例如下
use den1008\ProgressStatus\handlers\StdOutStatusHandler; // define status $processor = new StatusProcessor([new StdOutStatusHandler()]); $processor->setTotal(100); for ($i = 0; $i < 100; $i++){ $processor->increaseProgress()->say('processing'); }
执行脚本时,在控制台将输出以下行
[2019-04-16 19:36:51][ 1.0%][ 0.00] processing [2019-04-16 19:36:51][ 2.0%][ 0.00] processing ... [2019-04-16 19:36:51][100.0%][ 0.00] processing
为了不在每次都打印新行,而是更新同一行,需要这样做
$handler = new StdOutStatusHandler(0); // изменение глубины вывода вложенных прогрессов
默认情况下,隐藏的嵌套进度深度为 1,即调用 say() 和 sayStage() 方法时,深度 1 的每条消息都会在新行中输出。对于深度 2 的消息,进度将输出在同一行上。一般情况:如果隐藏消息的深度设置为 N,则深度 <= N 的所有消息都会在新行中输出,而深度 > N 的消息将输出在同一行上。
要更改输出消息的模板,需要更改以下公共字段
/** @var string Формат вывода */ public $mainFormat = "[{%date%} {%time%}][{%commonPercent%}%][{%totalTime%}] {%msg%}"; /** @var string Формат вывода скрытых однострочных статусов */ public $hideFormat = "[{%date%} {%time%}][{%commonPercent%}%][{%totalTime%}] └ {%msg%}";
- 用于格式化消息的是 FormatMessageTrait。可用的输出参数
- {%date%} - 当前日期
- {%time%} - 当前时间
- {%progress%} - 当前进度
- {%total%} - 最大进度
- {%time%} - 当前时间
- {%percent%} - 当前执行百分比
- {%commonPercent%} - 总执行百分比
- {%totalTime%} - 每一步的总时间(从开始工作的时间点)
- {%stepTime%} - 每一步的耗时(从最后一步的时间点)
- {%msg%} - 消息
FileStatusHandler
该组件将进度信息输出到文件。简单的使用示例如下
use den1008\ProgressStatus\handlers\FileStatusHandler; // define status $processor = new StatusProcessor([new FileStatusHandler('path/to/file')]); $processor->setTotal(100); for ($i = 0; $i < 100; $i++){ $processor->increaseProgress()->say('processing'); }
执行脚本时,在文件中将记录以下行
[2019-04-16 19:36:51][ 1.0%] processing [2019-04-16 19:36:51][ 2.0%] processing ... [2019-04-16 19:36:51][100.0%] processing
要更改输出消息的模板,需要更改以下类的字段
/** @var string Формат вывода */ public $format = "[{%date%} {%time%}][{%commonPercent%}] {%msg%}";
与 StdOutStatusHandler 类似,用于格式化消息也使用 FormatMessageTrait(参见上面的描述)。
测试
用于测试的是 PhpUnit
./vendor/bin/phpunit tests/