Public vs private disk — php artisan storage:link
Concept
Custom filesystem drivers allow integrating any storage backend — Cloudflare R2, Backblaze B2, Google Cloud Storage, DigitalOcean Spaces, or a completely custom implementation — into Laravel's Storage facade.
Flysystem adapters: Laravel's filesystem layer is built on league/flysystem. Most cloud storage services have a Flysystem adapter package. You register the adapter in a service provider, and it becomes a new disk driver.
Registration: Storage::extend(string $driver, callable $callback) in a service provider's boot(). The callback receives $app and $config (from config/filesystems.php). Return a Illuminate\Filesystem\FilesystemAdapter wrapping a Flysystem filesystem.
Community adapters:
league/flysystem-aws-s3-v3: AWS S3 / R2 / Spaces (S3-compatible).league/flysystem-google-cloud-storage: Google Cloud Storage.spatie/flysystem-dropbox: Dropbox.- Most cloud providers offer an S3-compatible API — use the S3 adapter with a custom endpoint.
Cloudflare R2 (S3-compatible): Configure the S3 driver with R2's endpoint URL. No extra adapter needed.
Custom adapter: Implement League\Flysystem\FilesystemAdapter interface for completely custom backends (custom CMS asset storage, corporate FTP, etc.).
Code Example
<?php
// Cloudflare R2 — uses S3 driver with custom endpoint
// config/filesystems.php
'r2' => [
'driver' => 's3',
'key' => env('R2_ACCESS_KEY_ID'),
'secret' => env('R2_SECRET_ACCESS_KEY'),
'region' => 'auto',
'bucket' => env('R2_BUCKET'),
'url' => env('R2_URL'), // your custom domain or R2 public URL
'endpoint' => env('R2_ENDPOINT'), // https://accountid.r2.cloudflarestorage.com
'use_path_style_endpoint' => true,
],
// Use it exactly like any other disk
Storage::disk('r2')->put('uploads/file.txt', $content);
Storage::disk('r2')->temporaryUrl('private/doc.pdf', now()->addHour());
// Google Cloud Storage via custom driver
// composer require superbalist/flysystem-google-cloud-storage
class FilesystemServiceProvider extends \Illuminate\Support\ServiceProvider
{
public function boot(): void
{
\Illuminate\Support\Facades\Storage::extend('gcs', function($app, $config) {
$storageClient = new \Google\Cloud\Storage\StorageClient([
'keyFilePath' => $config['key_file'],
]);
$adapter = new \Superbalist\Flysystem\GoogleStorage\GoogleStorageAdapter(
$storageClient,
$storageClient->bucket($config['bucket'])
);
return new \Illuminate\Filesystem\FilesystemAdapter(
new \League\Flysystem\Filesystem($adapter),
$adapter,
$config
);
});
}
}
// config/filesystems.php — use the custom driver
'gcs' => [
'driver' => 'gcs',
'key_file' => env('GCS_KEY_FILE'),
'bucket' => env('GCS_BUCKET'),
],
// Usage
Storage::disk('gcs')->put('backups/data.json', $data);
$url = Storage::disk('gcs')->url('images/photo.jpg');