spatie/temporary-directory
Create, use, and automatically clean up temporary directories in PHP. Spatie TemporaryDirectory makes it easy to generate a temp folder (in your system temp path), build file paths inside it, and delete everything when you’re done.
Install via Composer:
composer require spatie/temporary-directory
use Spatie\TemporaryDirectory\TemporaryDirectory;
$tempDir = TemporaryDirectory::make()->create();
// Store files in temp directory
file_put_contents($tempDir->path('upload.csv'), $csvData);
// Process files (e.g., with Laravel's Filesystem)
$processed = Storage::disk('local')->exists($tempDir->path('upload.csv'));
// Cleanup automatically
unset($tempDir); // Triggers deletion via deleteWhenDestroyed()
Key Starting Points:
TemporaryDirectory::make() - Static factory method$tempDir->path('subdir/file.txt') - Generate absolute pathsdeleteWhenDestroyed() - Enable automatic cleanup$tempDir = TemporaryDirectory::make()
->location(storage_path('app/temp'))
->permission(0755)
->create();
try {
// 1. Write input
file_put_contents($tempDir->path('input.json'), $request->json());
// 2. Process with external tool
$output = shell_exec("some-process {$tempDir->path('input.json')}");
// 3. Store results
file_put_contents($tempDir->path('output.json'), $output);
// 4. Return path for download
return response()->download($tempDir->path('output.json'));
} finally {
$tempDir->delete(); // Explicit cleanup
}
public function test_file_processing()
{
$tempDir = TemporaryDirectory::make()
->deleteWhenDestroyed()
->create();
// Write test file
file_put_contents($tempDir->path('test.csv'), 'data');
// Assert processing works
$this->assertTrue(file_exists($tempDir->path('test.csv')));
// Test cleanup
unset($tempDir);
$this->assertFalse(file_exists($tempDir->getPath()));
}
$tempDir = TemporaryDirectory::make(storage_path('framework/temp'))
->name('laravel-process')
->force() // Overwrite if exists
->create();
// Use with Laravel Filesystem
Storage::disk('local')->put($tempDir->path('config.json'), $config);
With Laravel Queues:
public function handle()
{
$tempDir = TemporaryDirectory::make()
->deleteWhenDestroyed()
->create();
// Process large file
$this->processLargeFile($tempDir->path('input.pdf'));
// Store results in DB with path
$this->storeResult($tempDir->path('output.pdf'));
}
With Laravel Artisan Commands:
protected $tempDir;
protected function setup()
{
$this->tempDir = TemporaryDirectory::make()
->location(sys_get_temp_dir())
->create();
}
protected function tearDown(): void
{
$this->tempDir->delete();
}
Permission Issues
0777 may cause problems on shared hosting->permission(0755)
Race Conditions
force() with named directories->name('temp-'.Str::uuid())
Memory Leaks
deleteWhenDestroyed()$tempDir = TemporaryDirectory::make()->create();
try {
// Work
} finally {
unset($tempDir);
}
Path Resolution
path() returns absolute paths - verify with:
$this->assertStringStartsWith(sys_get_temp_dir(), $tempDir->path('file'));
Verify Directory Exists:
if (!$tempDir->exists()) {
throw new \RuntimeException("Temporary directory not created");
}
Check Cleanup:
$tempDir->delete();
$this->assertFalse(file_exists($tempDir->getPath()), "Directory not deleted");
Custom Cleanup Logic
$tempDir = TemporaryDirectory::make()->create();
$tempDir->onDelete(function ($path) {
// Custom cleanup (e.g., log deletion)
Log::info("Deleted temp dir: {$path}");
});
Subclassing for Domain-Specific Needs
class UploadTemporaryDirectory extends TemporaryDirectory
{
public function __construct()
{
parent::__construct(storage_path('app/uploads/temp'));
}
public function create(): self
{
return $this->permission(0750)->create();
}
}
Testing Edge Cases
// Test directory creation under heavy load
$tempDirs = collect(range(1, 100))->map(fn($i) =>
TemporaryDirectory::make()->name("test-{$i}")->create()
);
// Verify all created
$tempDirs->each(fn($dir) => $this->assertTrue($dir->exists()));
// Cleanup
$tempDirs->each(fn($dir) => $dir->delete());
Windows Path Handling
$tempDir->path('subdir/file.txt') // Works on both Windows/Linux
SELinux Contexts
->permission(0777)
->create()
->chmod(0755); // Additional chmod if needed
Large Files
$tempDir = TemporaryDirectory::make()
->location(sys_get_temp_dir())
->create();
// Use stream processing instead of loading entire file
Directory Creation Overhead
$tempDirs = collect(range(1, 10))->map(fn($i) =>
TemporaryDirectory::make()->name("batch-{$i}")->create()
);
Memory Management
$tempDir = TemporaryDirectory::make()->create();
// ... long process ...
$tempDir->delete(); // Force cleanup
Filesystem Iterator Warning
FilesystemIterator which may be slow on very large directories (>100K files)
```markdown
### Laravel-Specific Tips
1. **Using with Laravel Filesystem**
```php
$tempDir = TemporaryDirectory::make(storage_path('app/temp'))->create();
Storage::disk('local')->put($tempDir->path('file.json'), $data);
public function handle()
{
$tempDir = TemporaryDirectory::make()
->deleteWhenDestroyed()
->create();
// Process with Laravel's filesystem
$this->processWithStorage($tempDir->path('input.csv'));
// Store result path in DB
Result::create([
'path' => $tempDir->path('output.json'),
'status' => 'processing'
]);
}
protected $tempDir;
protected function handle()
{
$this->tempDir = TemporaryDirectory::make()
->location(sys_get_temp_dir())
->create();
// Command logic using $this->tempDir
}
protected function tearDown(): void
{
$this->tempDir->delete();
}
public function test_file_upload_processing()
{
$tempDir = TemporaryDirectory::make()
->deleteWhenDestroyed()
->create();
Storage::fake('local');
Storage::disk('local')->put($tempDir->path('test.pdf'), $pdfContent);
$this->assertTrue(
Storage::disk('local')->exists($tempDir->path('test.pdf'))
);
unset($tempDir);
$this->assertFalse(
Storage::disk('local')->exists($tempDir->getPath())
);
}
// In a service provider
$this->app->bind(TemporaryDirectory::class, function ($app) {
return TemporaryDirectory::make(storage_path('app/temp'))
->permission(0750)
->deleteWhenDestroyed();
});
How can I help you explore Laravel packages today?