【问题标题】:How to use symfony console progress Helper?如何使用 symfony 控制台进度助手?
【发布时间】:2014-02-19 22:13:50
【问题描述】:

举个例子Symfony Progress Helper

我不确定如何使用它。我正在使用usleep,因为我希望进度条一直运行到任务完成。假设任务是一个可以做很多其他事情的方法,当它完成时它返回 true。当它返回 true 时,我想使用 setCurrent 来完成进度条。

$progress = $this->getHelperSet()->get('progress');

$progress->start($this->output, 100);

$i = 0;
while ($i++ < 100) {
    usleep(100000);

    $progress->advance();

}

//do stuff and return true when it's done
if($this->doStuff()) $progress->setCurrent(100);

$progress->finish();

在文档中我不清楚这是如何工作的。如果我将我的方法放入循环中,它将运行 100 次。但是如果我把它放在循环之外,那么循环将在运行我的方法之前运行 100 次。另外,如果我把它放在 $progress->finish() 之外,我会收到一个错误,我必须 start() 进度条,这是有道理的,但是如果我把它放在finish() 里面,我会得到一个逻辑异常“你不能让进度倒退酒吧”

感谢您的帮助。示例用法会很棒。

更新: 也许这是不可能的。

让我解释一下我正在尝试做些什么来清除它。

我想在屏幕上运行一个进度条。它设置的迭代时间比 doStuff() 实际运行所需的时间长。 doStuff() 基本上是我课堂上的一种 fire() 方法,可以做很多其他事情,包括下载和复制文件。但是 doStuff() 只运行一次。我需要进度条在 doStuff() 运行的整个过程中都在运行,但是当 doStuff() 完成时,我希望能够将进度条推进到最后,或者不管它在循环中的哪个位置终止它。

我尝试将 progress->advance() 放在我的 doStuff() 方法中,但它仍然需要一个循环,因为它只前进一次。所以这就是为什么我需要 doStuff() 与进度条循环分开但能够从 doStuff() 中终止它。

【问题讨论】:

  • 你不需要使用setCurrent(),你应该在你正在处理的循环中调用advance()(我假设在doStuff()的某个地方)
  • 我不明白。 doStuff 不是循环。这是一个长时间运行的进程,它调用其他方法、实例化类等。但是当它运行时,我希望进度条在屏幕上运行。这就是为什么我会在我的 doStuff 完成后使用 setCurrent 将其推进到最后。
  • 这就是我的意思,您需要将您的ProgressHelper 集成到您的doStuff() 方法中,以便您可以在此过程中递增它,您的while 循环正在推进之前的进度doStuff() 方法实际上已被调用。您的 doStuff() 方法实际上需要很长时间才能运行它需要 ProgressHelper 吗?
  • 我现在明白了。我根本不需要循环。在 doStuff() 中的每个任务之后,只需一个回调即可推进栏

标签: php symfony console progress-bar


【解决方案1】:

感谢 JamesHalsall cmets 的答案是进度条不能以这种方式工作。如果我想多次循环执行单个任务或一组任务,Symfony 中的示例就可以了。

但是在这种情况下,只有一个任务,我需要将回调传递给 doStuff() 的 doStuff() 方法,以便 doStuff() 可以推进进度条。这里不需要循环。还发现Advance方法接受一个整数作为前进多少步的参数。

因此,通过一些基本的数学运算和回调,这实际上是。将进度条设置为 100 并且 doStuff() 中的 4 个任务 100/4 = 25 是推进进度条的步数。

这是一个对我有用的例子。当然,在 4 个任务中抛出的异常将停止一切,因此即使特定任务失败,也不用担心进度条完成。

    protected function update()
    {
        $this->progress = $this->getHelperSet()->get('progress');
        $this->progress->setBarCharacter('<comment>=</comment>');
        $this->progress->setBarWidth(50);
        $this->progress->start($this->output, 100);
        $done = false;


        $result = false;

        $advance = function($steps)
        {
            $this->progress->advance($steps);
        };

        $result = $this->doStuff($advance);

        $this->progress->finish();

        if($result === true)
        {
            $this->displayOutput("I be done foo!");
        }
        else
        {
            $this->displayOutput("Somethin went wrong foo!");
        }

    }


    protected function doStuff($callback)
    {
        //simulate tasks with usleep
        //perfom task 1
        usleep(500000);
        $callback(25);

        //perform task 2
        usleep(500000);
        $callback(25);

        //task 3
        usleep(5000000);
        $callback(25);

        //task 4
        usleep(3000000);
        $callback(25);

        //at this point the progress bar is finished so you can return whatever is appropriate here
        return true;
    }

【讨论】:

    【解决方案2】:

    您似乎将 100 设置为与其他任何内容无关的任意数字。

    你可以在 doStuff 中调用一个 getter 来更新父命令。

    $progress = $this->getHelperSet()->get('progress');
    
    $progress->start($this->output, 100);
    
    $i = 0;
    while ($i++ < 100) {
        if (null === $this->doStuff() || $this->doStuff()->getCount() >= $i) {
            $progress->advance();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-18
      • 2014-10-20
      • 1970-01-01
      • 2015-11-21
      • 2023-03-21
      • 1970-01-01
      相关资源
      最近更新 更多