0

Custom notification channels

Advanced5 min read·lv-21-005

Concept

File storage in Laravel is abstracted by the Storage facade, built on the Flysystem library. The same API works with local disk, S3, R2, GCS, FTP, and SFTP — changing the disk config switches backends without touching application code.

Disks: Named storage configurations in config/filesystems.php. The default disk is used by Storage::put() etc. with no disk specified. Storage::disk('s3')->put(...) uses a specific disk.

Key operations:

  • Storage::put($path, $contents): Write (creates directories automatically).
  • Storage::get($path): Read file contents.
  • Storage::exists($path) / Storage::missing($path).
  • Storage::delete($path) / Storage::delete(['a', 'b']).
  • Storage::move($from, $to): Move/rename.
  • Storage::copy($from, $to): Copy.
  • Storage::url($path): Public URL. Only works for public disks.
  • Storage::temporaryUrl($path, $expiry): Signed URL. S3/R2 only.
  • Storage::size($path): File size in bytes.
  • Storage::lastModified($path): Unix timestamp of last modification.
  • Storage::mimeType($path): MIME type.

Visibility: public = world-readable URL, private = no direct URL access.

  • Storage::setVisibility($path, 'public').
  • Storage::put($path, $contents, 'public') — third arg sets visibility.

Code Example

php
<?php
use Illuminate\Support\Facades\Storage;

// Write
Storage::put('reports/sales-2024.csv', $csvContent);
Storage::put('images/avatar.jpg', $imageData);
Storage::put('files/doc.pdf', $contents, 'public'); // publicly accessible

// Read
$contents = Storage::get('reports/sales-2024.csv');
$json     = json_decode(Storage::get('config/settings.json'), true);

// Check existence
if (Storage::exists('reports/sales-2024.csv')) { ... }
if (Storage::missing('cache/stats.json')) {
    // generate and store
}

// Delete
Storage::delete('reports/old-report.csv');
Storage::delete(['img/1.jpg', 'img/2.jpg', 'img/3.jpg']);

// Directory operations
Storage::makeDirectory('reports/2024');
Storage::deleteDirectory('temp');
$files = Storage::files('reports');
$allFiles = Storage::allFiles('reports'); // recursive
$dirs = Storage::directories('reports');

// URLs
$url = Storage::url('images/avatar.jpg');          // public URL (/storage/images/avatar.jpg)
$url = Storage::disk('s3')->url('files/doc.pdf');  // https://bucket.s3.../files/doc.pdf

// Temporary URL (S3/R2) — signed, expires in 30 min
$tempUrl = Storage::disk('s3')->temporaryUrl(
    'private-files/contract.pdf',
    now()->addMinutes(30)
);
// Share this URL — it expires automatically

// Storing uploaded files
public function uploadAvatar(Request $request, User $user)
{
    $path = $request->file('avatar')->store('avatars', 's3');
    // Returns: "avatars/random-uuid.jpg"
    $user->update(['avatar_path' => $path]);
}

// Cross-disk operations
$contents = Storage::disk('local')->get('exports/data.json');
Storage::disk('s3')->put('backups/data.json', $contents);