如何通过交互调用工匠控制台命令

Pep*_*ier 7 php console command laravel laravel-artisan

我目前正在 Laravel 5.1 项目中创建一个 php artisan 控制台命令,并想从我的控制台命令中调用另一个控制台命令。我想调用的这个第三方命令不接受任何选项或参数,而是通过交互式问题接收其输入。

我知道我可以调用带有选项和参数的命令,如下所示:

$this->call('command:name', ['argument' => 'foo', '--option' => 'bar']);

我也知道我可以从命令行调用交互式命令而无需像这样的交互:

php artisan 命令:名称 --no-interaction


但是我怎样才能在我的命令中回答这些交互式问题呢?

我想做类似下面的事情(伪代码)。

$this->call('command:name', [
    'argument' => 'foo', 
    '--option' => 'bar'
], function($console) {
    $console->writeln('Yes'); //answer an interactive question 
    $console-writeln('No'); //answer an interactive question 
    $console->writeln(''); //skip answering an interactive question 
} );
Run Code Online (Sandbox Code Playgroud)

当然,以上不起作用,因为$this->call($command, $arguments)不接受第三个回调参数。

从控制台命令调用控制台命令时如何回答交互式问题?

mot*_*tia 4

我有另一个解决方案,它是调用执行“php artisan”的 symfony 命令,而不是使用 artisan 子命令。我认为这比修补第三方代码更好。

这是一个管理此问题的特质。

use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
trait ArtisanCommandTrait{
    public function executeArtisanCommand($command, $options){
        $stmt = 'php artisan '. $command . ' ' . $this->prepareOptions($options);

        $process = new Process($stmt);
        $process->run();
        // executes after the command finishes
        if (!$process->isSuccessful()) {
            throw new ProcessFailedException($process);
        }
        return $process->getOutput();
    }
    public function prepareOptions($options){
            $args = [];
            $opts = [];
            $flags = [];
            foreach ($options as $key => $value) {
                if(ctype_alpha(substr($key, 0, 1)))
                    $args[] = $value;
                else if(starts_with($key, '--')){
                    $opts[] = $key. (is_null($value) ? '' : '=' . $value) ;
                }
                else if(starts_with($key, '-')){
                    $flags[] = $key;
                }
            }
            return   implode(' ', $args) . ' '
                    .implode(' ', $opts). ' '
                    .implode(' ', $flags);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您应该能够传递任何工匠特殊选项,例如无交互。

public function handle(){
    $options = [
            'argument' => $argument,
            '--option' => $options,         // options should be preceded by --
            '-n' => null                    // no-interaction option
        ];
    $command = 'your:command';
    $output = $this->executeArtisanCommand($command, $options);        
    echo $output;
}
Run Code Online (Sandbox Code Playgroud)

您可以从此要点下载该特征