-
Notifications
You must be signed in to change notification settings - Fork 11.5k
Description
Laravel Version
12.21.0
PHP Version
8.4
Database Driver & Version
—
Description
The Artisan Console Components, which render things like interactive question prompts, progress bars, and so on, use the default Output instance only. Instead, they should—if it is available—use the Error Output to write text not part of the command's output.
For a concrete example, imagine a command with a --json
flag that will return some JSON data to be piped to another command or written to a file. The command can take a while though, so it would be great to use the task()
helper to show step progress, especially when running in non-JSON mode.
This won't work, though: The task output will be included in the output file and thus break the JSON.
$ php artisan some:command > output.json
$ head -n+3 output.json
Doing work ...................................... 1s DONE
[
{
If the console components were writing non-output related messages to stderr instead, this would work beautifully: Process logs (like task progress) is rendered on the terminal, while the JSON output gets sent to the pipe:
$ php artisan some:command > output.json
Doing work ...................................... 1s DONE
$ head -n+3 output.json
[
{
"nice": "valid JSON!"
If there is a desire to improve this, I'd be willing to create a PR.
Steps To Reproduce
Here's a sample command that shows the behaviour:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use function json_encode;
use function sleep;
use const JSON_PRETTY_PRINT;
#[AsCommand('some:command')]
class SomeCommand extends Command
{
protected $signature = 'some:command {--json}';
public function handle(): int
{
$this->components->task('Doing work', fn () => sleep(1));
if ($this->option('json')) {
$this->output->writeln(json_encode([['nice' => 'valid JSON!']], JSON_PRETTY_PRINT));
return 0;
}
$this->table(['Key', 'Value'], [['nice', 'a table!']]);
return 0;
}
}