league/flysystem is a popular PHP package that provides a robust, unified, and easy-to-use abstraction layer for various file storage systems. Its primary goal is to allow developers to interact with different storage solutions—such as local disks, AWS S3, Azure Blob Storage, FTP, SFTP, Dropbox, Google Cloud Storage, and many others—using a single, consistent API. This eliminates the need to learn and implement separate APIs for each storage service, making your application more portable and maintainable.
Key Concepts:
1. Adapters: These are the core components that encapsulate the logic for interacting with a specific storage backend. For example, `LocalFilesystemAdapter` handles interactions with the local disk, `AwsS3V3Adapter` interfaces with Amazon S3, and so on. You choose and install the adapter(s) relevant to your storage needs.
2. Filesystem: This is the primary class you interact with. It takes an adapter as a dependency and exposes a consistent set of methods for common file operations. You instantiate `Filesystem` with an adapter, and then all your file operations go through this `Filesystem` instance, regardless of the underlying storage.
3. Storage Abstraction: Flysystem abstracts away the differences between various file systems. Whether you're writing to a local file, uploading to S3, or listing files on an FTP server, the method calls (`write()`, `read()`, `listContents()`, `delete()`, etc.) remain the same.
Benefits of using league/flysystem:
* Portability: Easily switch between different storage backends (e.g., from local disk to S3) with minimal code changes, primarily by swapping out the adapter.
* Testability: Mock file system operations during testing without actually hitting a real storage service, leading to faster and more reliable tests.
* Unified API: Provides a clean, consistent, and intuitive API for common file operations across all supported storage types.
* Extensibility: If a specific storage backend isn't natively supported, you can create custom adapters to integrate it.
* Error Handling: Provides consistent exception handling for storage-related issues.
By centralizing file interactions through Flysystem, developers can build more flexible, resilient, and future-proof applications that aren't tightly coupled to a specific storage provider.
Example Code
<?php
require 'vendor/autoload.php';
use League\Flysystem\Filesystem;
use League\Flysystem\Local\LocalFilesystemAdapter;
use League\Flysystem\StorageAttributes;
use League\Flysystem\UnableToReadFile;
use League\Flysystem\FilesystemException;
// 1. Define the base path for local storage
// This will create a 'storage' directory in your current working directory
$basePath = __DIR__ . DIRECTORY_SEPARATOR . 'storage';
// Create the directory if it doesn't exist
if (!is_dir($basePath)) {
mkdir($basePath, 0777, true);
}
// 2. Instantiate a local filesystem adapter
// This adapter tells Flysystem how to interact with the local disk.
$adapter = new LocalFilesystemAdapter($basePath);
// 3. Instantiate the Filesystem object
// This is the main object you'll use to perform file operations.
$filesystem = new Filesystem($adapter);
echo "\n--- Starting Flysystem Operations ---\n";
try {
$filePath = 'my-document.txt';
$directoryPath = 'my-documents';
$nestedFilePath = 'my-documents/nested/report.pdf';
$copyToPath = 'my-documents/copy-of-document.txt';
// --- Write a file ---
$content = 'Hello, Flysystem! This is a test document.';
$filesystem->write($filePath, $content);
echo "Written file: {$filePath}\n";
// --- Check if a file exists ---
if ($filesystem->fileExists($filePath)) {
echo "File exists: {$filePath}\n";
} else {
echo "File does NOT exist: {$filePath}\n";
}
// --- Read a file ---
$readContent = $filesystem->read($filePath);
echo "Content of {$filePath}: \"{$readContent}\"\n";
// --- Update (overwrite) a file ---
$newContent = 'This is the updated content for the document.';
$filesystem->write($filePath, $newContent);
echo "Updated file: {$filePath}\n";
echo "New content of {$filePath}: \"{$filesystem->read($filePath)}\"\n";
// --- Create a directory ---
$filesystem->createDirectory($directoryPath);
echo "Created directory: {$directoryPath}\n";
// --- Write a file within a directory (including nested directory creation) ---
$nestedContent = 'This is a nested report file.';
$filesystem->write($nestedFilePath, $nestedContent);
echo "Written nested file: {$nestedFilePath}\n";
// --- Copy a file ---
$filesystem->copy($filePath, $copyToPath);
echo "Copied {$filePath} to {$copyToPath}\n";
if ($filesystem->fileExists($copyToPath)) {
echo "Copied file exists: {$copyToPath}\n";
}
// --- List contents of a directory ---
echo "\nListing contents of '{$directoryPath}':\n";
$contents = $filesystem->listContents($directoryPath, true); // true for recursive
foreach ($contents as $item) {
// $item is an instance of StorageAttributes (or one of its specialized subclasses)
if ($item->isFile()) {
echo "- File: {$item->path()}\n";
} elseif ($item->isDir()) {
echo "- Dir: {$item->path()}\n";
}
}
// --- Move (rename) a file ---
$newPathAfterMove = 'my-documents/moved-document.txt';
$filesystem->move($copyToPath, $newPathAfterMove);
echo "Moved {$copyToPath} to {$newPathAfterMove}\n";
if ($filesystem->fileExists($newPathAfterMove)) {
echo "Moved file exists: {$newPathAfterMove}\n";
$filesystem->delete($newPathAfterMove);
echo "Deleted moved file: {$newPathAfterMove}\n";
}
// --- Delete files and directories ---
$filesystem->delete($filePath);
echo "Deleted file: {$filePath}\n";
// Deleting a directory will also delete its contents recursively
$filesystem->deleteDirectory($directoryPath);
echo "Deleted directory and its contents: {$directoryPath}\n";
} catch (FilesystemException $exception) {
// Handle any filesystem errors
echo "Error: " . $exception->getMessage() . "\n";
} catch (UnableToReadFile $exception) {
// Handle specific error for reading files
echo "Error reading file: " . $exception->getMessage() . "\n";
} catch (Throwable $exception) {
// Catch any other unexpected errors
echo "An unexpected error occurred: " . $exception->getMessage() . "\n";
}
echo "\n--- Flysystem Operations Complete ---\n";
// You can manually inspect the 'storage' directory to see the results
// It should be empty after all delete operations.
?>








league/flysystem