Table of Contents
Here’s a pattern I reach for any time I need temporary file operations in an artisan command or queue job: Storage::build().
Most Laravel developers know about configuring disks in config/filesystems.php. But what happens when you need a quick, disposable filesystem rooted in the system temp directory? You don’t want to pollute your configured disks with throwaway stuff.
The Pattern
use Illuminate\Support\Facades\Storage;
$storage = Storage::build([
'driver' => 'local',
'root' => sys_get_temp_dir(),
]);
// Now use it like any other disk
$storage->makeDirectory('my-export');
$storage->put('my-export/report.csv', $csvContent);
// Clean up when done
$storage->deleteDirectory('my-export');
This creates a filesystem instance on the fly, pointed at /tmp (or whatever your OS temp directory is). No config file changes. No new disk to maintain.
Why This Beats the Alternatives
You might be tempted to just use raw PHP file functions:
// Don't do this
file_put_contents('/tmp/my-export/report.csv', $csvContent);
But then you lose all the niceties of Laravel’s filesystem API — directory creation, deletion, visibility management, and consistent error handling.
You could also define a temp disk in your config:
// config/filesystems.php
'temp' => [
'driver' => 'local',
'root' => sys_get_temp_dir(),
],
But that’s permanent config for a temporary need. Storage::build() keeps it scoped to the code that actually needs it.
A Real-World Use Case
This shines in artisan commands that generate files, process them, and clean up:
class GenerateReportCommand extends Command
{
protected $signature = 'report:generate {userId}';
private Filesystem $storage;
public function __construct()
{
parent::__construct();
$this->storage = Storage::build([
'driver' => 'local',
'root' => sys_get_temp_dir(),
]);
}
public function handle()
{
$dir = 'report-' . $this->argument('userId');
$this->storage->makeDirectory($dir);
try {
// Generate CSV
$this->storage->put("$dir/data.csv", $this->buildCsv());
// Maybe encrypt it
$encrypted = $this->encrypt("$dir/data.csv");
// Upload somewhere permanent
Storage::disk('s3')->put("reports/$dir.csv.gpg",
$this->storage->get($encrypted)
);
} finally {
// Always clean up
$this->storage->deleteDirectory($dir);
}
}
}
The try/finally ensures temp files get cleaned up even if something throws. The command’s temp filesystem stays completely isolated from the rest of your app.
Storage::build() has been available since Laravel 9. If you’re still using raw file_put_contents() calls for temp files, give this a try.

Leave a Reply