Streaming Command Output To The Browser
Following on from my last post about output buffer streaming I wondered if it was possible to stream the output from a Laravel Artisan command to the browser.
You might be asking "but why?" good question! The answer is simply because I wanted to know if you could.
Spoiler Alert: You can and it's easy
After spelunking though the Laravel/Symphony command handling code for a while I discovered that most of the code to do this is already written. Symphony includes a StreamOutput
class and the Artisan::call()
method accepts a custom output buffer class.
All I needed to do hook it up to the php://output stream:
$outputBuffer = new class extends \Symfony\Component\Console\Output\StreamOutput
{
public function __construct()
{
parent::__construct(fopen('php://output', 'w'));
}
};
Artisan::call('command:name', outputBuffer: $outputBuffer);
Note the anonymous class is not required, it can be a regular class
While this works it isn't very readable because the output contains \n
rather than <br>
. We can convert these on the fly like this:
$outputBuffer = new class extends \Symfony\Component\Console\Output\StreamOutput
{
public function __construct()
{
parent::__construct(fopen('php://output', 'w'));
}
protected function doWrite(string $message, bool $newline)
{
$message = str_replace("\n", '<br>', $message);
if ($newline) {
$message .= '<br>';
}
parent::doWrite($message, false);
}
};