blazon / psr11-flysystem
Flysystem Factories for PSR-11
Requires
- php: >=8.4
- league/flysystem: ^3.30
- league/flysystem-local: ^3.30
- league/flysystem-memory: ^3.30
- psr/container: ^1.1 || ^2.0
Requires (Dev)
- async-aws/s3: ^3.0
- azure-oss/storage-blob-flysystem: ^2.2
- fakerphp/faker: ^1.24
- friendsofphp/php-cs-fixer: ^3.95
- infection/infection: ^0.35.6
- laminas/laminas-servicemanager: ^4.4
- league/container: ^5.0
- league/flysystem-async-aws-s3: ^3.30
- league/flysystem-aws-s3-v3: ^3.30
- league/flysystem-ftp: ^3.30
- league/flysystem-google-cloud-storage: ^3.30
- league/flysystem-gridfs: ^3.30
- league/flysystem-path-prefixing: ^3.30
- league/flysystem-read-only: ^3.30
- league/flysystem-sftp-v3: ^3.30
- league/flysystem-webdav: ^3.30
- league/flysystem-ziparchive: ^3.30
- php-di/php-di: ^7.1
- phpmd/phpmd: ^3.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.1
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^13.4
- pimple/pimple: ^3.5
- shipmonk/composer-dependency-analyser: ^1.8
- slim/slim: ^4.15
- symfony/dependency-injection: ^8.0
- wshafer1/phpstan-extended-rules: *
Suggests
- azure-oss/storage-blob-flysystem: Required to use the Azure Blob Storage adapter
- league/flysystem-async-aws-s3: Required to use the AsyncAws S3 adapter
- league/flysystem-aws-s3-v3: Required to use the AWS S3 adapter
- league/flysystem-ftp: Required to use the FTP adapter
- league/flysystem-google-cloud-storage: Required to use the Google Cloud Storage adapter
- league/flysystem-gridfs: Required to use the MongoDB GridFS adapter
- league/flysystem-path-prefixing: Required to use the Path Prefixing decorator
- league/flysystem-read-only: Required to use the Read-Only decorator
- league/flysystem-sftp: Required to use the SFTP adapter with phpseclib v2 (sftpv2)
- league/flysystem-sftp-v3: Required to use the SFTP adapter
- league/flysystem-webdav: Required to use the WebDAV adapter
- league/flysystem-ziparchive: Required to use the Zip Archive adapter
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-10 01:41:39 UTC
README
PSR-11 FlySystem
FlySystem Version 3 Factories for PSR-11. Requires PHP 8.4 or newer. If you need factories for Version 1 please see: https://github.com/wshafer/psr11-flysystem
Table of Contents
Installation
composer require blazon/psr11-flysystem
Usage
<?php
// Get the FlySystem FileSystem
$fileSystem = $container->get('myFileSystemService');
// Write to file
$fileSystem->write('test.txt', 'this is test');
Additional info can be found in the documentation
Containers
Any PSR-11 container wil work. In order to do that you will need to add configuration
and register a new service that points to Blazon\PSR11FlySystem\FlySystemFactory
Below are some specific container examples to get you started
Laminas Service Manager
// Create the container and define the services you'd like to use
$container = new \Laminas\ServiceManager\ServiceManager([
'factories' => [
// FlySystem using the default keys.
'fileSystem' => \Blazon\PSR11FlySystem\FlySystemFactory::class,
// FlySystem using a different filesystem configuration
'other' => [\Blazon\PSR11FlySystem\FlySystemFactory::class, 'other'],
],
'services' => [
// Config
'config' => [
'flysystem' => [
'filesystems' => [
// At the bare minimum you must include a default filesystem.
'default' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/laminas'
],
],
],
// Some other filesystem. Keys are the names for each filesystem
'other' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/laminas'
],
],
],
],
],
],
],
]);
/** @var \League\Flysystem\FilesystemOperator $fileSystem */
$fileSystem = $container->get('other');
$fileSystem->write('test1.txt', 'this is a test');
print $fileSystem->read('test1.txt');
PHP-DI
use Blazon\PSR11FlySystem\FlySystemFactory;
use DI\ContainerBuilder;
use Psr\Container\ContainerInterface;
use function DI\factory;
$builder = new ContainerBuilder();
$builder->addDefinitions([
// FlySystem using the default keys.
'fileSystem' => factory(FlySystemFactory::class),
// FlySystem using a different filesystem configuration
'other' => fn(ContainerInterface $c) => FlySystemFactory::other($c),
// Config
'config' => [
'flysystem' => [
'filesystems' => [
// At the bare minimum you must include a default filesystem.
'default' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/php-di'
],
],
],
// Some other filesystem. Keys are the names for each filesystem
'other' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/php-di'
],
],
],
],
],
],
]);
$container = $builder->build();
/** @var \League\Flysystem\FilesystemOperator $fileSystem */
$fileSystem = $container->get('other');
$fileSystem->write('test1.txt', 'this is a test');
print $fileSystem->read('test1.txt');
League Container
use Blazon\PSR11FlySystem\FlySystemFactory;
use League\Container\Container;
$container = new Container();
// FlySystem using the default keys.
$container->addShared('fileSystem', fn() => (new FlySystemFactory())($container));
// FlySystem using a different filesystem configuration
$container->addShared('other', fn() => FlySystemFactory::other($container));
// Config
$container->add('config', [
'flysystem' => [
'filesystems' => [
// At the bare minimum you must include a default filesystem.
'default' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/league'
],
],
],
// Some other filesystem. Keys are the names for each filesystem
'other' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/league'
],
],
],
],
],
]);
/** @var \League\Flysystem\FilesystemOperator $fileSystem */
$fileSystem = $container->get('other');
$fileSystem->write('test1.txt', 'this is a test');
print $fileSystem->read('test1.txt');
Frameworks
Any framework that use a PSR-11 should work fine. Below are some specific framework examples to get you started
Mezzio
You'll need to add configuration and register the services you'd like to use. There are number of ways to do that
but the recommended way is to create a new config file config/autoload/flySystem.global.php
Configuration
config/autoload/flySystem.global.php
<?php
return [
'dependencies' => [
'factories' => [
// FlySystem using the default keys.
'fileSystem' => \Blazon\PSR11FlySystem\FlySystemFactory::class,
// FlySystem using a different filesystem configuration
'someOtherFilesystem' => [\Blazon\PSR11FlySystem\FlySystemFactory::class, 'someOtherFilesystem'],
],
],
'flysystem' => [
'filesystems' => [
// At the bare minimum you must include a default filesystem.
'default' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/mezzio'
],
],
],
// Some other filesystem. Keys are the names for each filesystem
'someOtherFilesystem' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/mezzio'
],
],
],
],
],
];
Laminas
You'll need to add configuration and register the services you'd like to use. There are number of ways to do that
but the recommended way is to create a new config file config/autoload/flySystem.global.php
Configuration
config/autoload/flySystem.global.php
<?php
return [
'service_manager' => [
'factories' => [
// FlySystem using the default keys.
'fileSystem' => \Blazon\PSR11FlySystem\FlySystemFactory::class,
// FlySystem using a different filesystem configuration
'someOtherFilesystem' => [\Blazon\PSR11FlySystem\FlySystemFactory::class, 'someOtherFilesystem'],
],
],
'flysystem' => [
'filesystems' => [
// At the bare minimum you must include a default filesystem.
'default' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/laminas'
],
],
],
// Some other filesystem. Keys are the names for each filesystem
'someOtherFilesystem' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/laminas'
],
],
],
],
],
];
Symfony
While there are other Symfony bundles out there, as of Symfony 3.3 the service container is now a PSR-11 compatible container. The following config below will get these factories registered and working in Symfony.
Configuration
app/config/config.yml (or equivalent)
parameters:
flysystem:
filesystems:
# At the bare minimum you must include a default filesystem.
default:
adapter:
type: local
options:
root: /tmp/symfony
# Some other filesystem. Keys are the names for each filesystem
someOtherFilesystem:
adapter:
type: local
options:
root: /tmp/symfony
Container Service Config
app/config/services.yml
services:
# FlySystem using the default keys.
fileSystem:
factory: 'Blazon\PSR11FlySystem\FlySystemFactory:__invoke'
class: 'League\Flysystem\FilesystemOperator'
arguments: ['@service_container']
public: true
# FlySystem using a different filesystem configuration
someOtherFilesystem:
factory: ['Blazon\PSR11FlySystem\FlySystemFactory', __callStatic]
class: 'League\Flysystem\FilesystemOperator'
arguments: ['someOtherFilesystem', ['@service_container']]
public: true
Blazon\PSR11FlySystem\FlySystemFactory:
class: 'Blazon\PSR11FlySystem\FlySystemFactory'
public: true
Example Usage
src/AppBundle/Controller/DefaultController.php
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
* @Route("/", name="homepage")
*/
public function indexAction(Request $request)
{
$fileSystem = $this->container->get('fileSystem');
$fileSystem->write('default.txt', 'Hi there');
$fileSystem = $this->container->get('someOtherFilesystem');
$fileSystem->write('other.txt', 'Hi there');
}
}
Slim
Slim 4 doesn't ship its own container, so bring any PSR-11 container and hand it to AppFactory. This example uses
PHP-DI.
composer require slim/slim slim/psr7 php-di/php-di
public/index.php
<?php
use Blazon\PSR11FlySystem\FlySystemFactory;
use DI\ContainerBuilder;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use function DI\factory;
require __DIR__ . '/../vendor/autoload.php';
$builder = new ContainerBuilder();
$builder->addDefinitions([
// FlySystem using the default keys.
'fileSystem' => factory(FlySystemFactory::class),
// FlySystem using a different filesystem configuration
'someOtherFilesystem' => fn(ContainerInterface $c) => FlySystemFactory::someOtherFilesystem($c),
// Config
'settings' => [
'flysystem' => [
'filesystems' => [
// At the bare minimum you must include a default filesystem.
'default' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/slim'
],
],
],
// Some other filesystem. Keys are the names for each filesystem
'someOtherFilesystem' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/tmp/slim'
],
],
],
],
],
],
]);
AppFactory::setContainer($builder->build());
$app = AppFactory::create();
// Example usage
$app->get('/example', function (Request $request, Response $response) {
/** @var \League\Flysystem\FilesystemOperator $fileSystem */
$fileSystem = $this->get('fileSystem');
$fileSystem->write('default.txt', 'Hi there');
/** @var \League\Flysystem\FilesystemOperator $fileSystem */
$fileSystem = $this->get('someOtherFilesystem');
$fileSystem->write('other.txt', 'Hi there');
return $response;
});
$app->run();
Configuration
Minimal Configuration
A minimal configuration would consist of at least defining one service and the "default" adapter.
Minimal Example (using Mezzio for the example)
<?php
return [
'dependencies' => [
'factories' => [
// FlySystem using the default keys.
'MyServiceName' => \Blazon\PSR11FlySystem\FlySystemFactory::class,
],
],
'flysystem' => [
'filesystems' => [
// Array Keys are the names used for the filesystem
'default' => [
'adapter' => [
'type' => 'local', # Adapter name or pre-configured service from the container
// Adapter specific options. See adapters below
'options' => [
'root' => '/path/to/root', // Path on local filesystem
],
],
],
],
],
];
Using this setup you will be using the "default" file system with the "default" adapter. In this example we will be using the local file adapter as the default.
Full Configuration
Note: A "default" adapter is required.
Full Example
<?php
return [
'flysystem' => [
'filesystems' => [
// Array Keys are the names used for the filesystem. Default entry required for filesystems
'default' => [
'adapter' => [
'type' => 'local', // Adapter name or pre-configured service from the container
// Adapter specific options. See adapters below
'options' => [
'root' => '/path/to/root', // Path on local filesystem
],
],
// Optional : FlySystem config. See FlySystem Config below
'config' => [
'visibility' => \League\Flysystem\Visibility::PUBLIC,
'public_url' => 'https://cdn.example.com/',
],
// Optional : Services from the container. See FlySystem Config below
'pathNormalizer' => 'myPathNormalizer',
'publicUrlGenerator' => 'myPublicUrlGenerator',
'temporaryUrlGenerator' => 'myTemporaryUrlGenerator',
],
'filesystemTwo' => [
'adapter' => [
'type' => 'memory', // Adapter name or pre-configured service from the container
'options' => [], // Adapter specific options. See adapters below
],
],
],
// Mount Manager configs. See Mount Manager below
'mounts' => [
'default' => [
'filesystems' => [
'local' => 'myFileSystemService', // Mount name => FlySystem service name
'memory' => 'myOtherService', // Mount name => FlySystem service name
],
// Optional : Mount Manager config. See Mount Manager below
'config' => [
'visibility' => \League\Flysystem\Visibility::PRIVATE,
],
],
],
],
];
FlySystem Config
Each filesystem entry can also set the config used by the FlySystem Filesystem, and the services
it uses for path normalization and URLs. Only the keys below are accepted. Any other key in
config is ignored, and a key that isn't set keeps FlySystem's default.
<?php
use League\Flysystem\ResolveIdenticalPathConflict;
use League\Flysystem\Visibility;
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/path/to/root',
],
],
'config' => [
'visibility' => Visibility::PUBLIC, // Optional : Visibility::PUBLIC or Visibility::PRIVATE
'directory_visibility' => Visibility::PUBLIC, // Optional : Visibility::PUBLIC or Visibility::PRIVATE
'retain_visibility' => true, // Optional : Keep visibility on copy and move (default: true)
// Optional : Base URL for publicUrl(). A string, or an array of URLs to spread files across
'public_url' => 'https://cdn.example.com/',
'allow_relative_path_traversal' => true, // Optional : Allow "../" in paths (default: true)
// Optional : When copying a file onto itself. ResolveIdenticalPathConflict::TRY (default),
// ResolveIdenticalPathConflict::FAIL or ResolveIdenticalPathConflict::IGNORE
'copy_destination_same_as_source' => ResolveIdenticalPathConflict::TRY,
// Optional : When moving a file onto itself. Same values as above
'move_destination_same_as_source' => ResolveIdenticalPathConflict::TRY,
],
// Optional : Service name of a League\Flysystem\PathNormalizer in your container
'pathNormalizer' => 'myPathNormalizer',
// Optional : Service name of a League\Flysystem\UrlGeneration\PublicUrlGenerator in your container
'publicUrlGenerator' => 'myPublicUrlGenerator',
// Optional : Service name of a League\Flysystem\UrlGeneration\TemporaryUrlGenerator in your container
'temporaryUrlGenerator' => 'myTemporaryUrlGenerator',
],
],
],
];
An invalid visibility, directory_visibility, public_url, copy_destination_same_as_source or
move_destination_same_as_source value throws an InvalidConfigException. So does a pathNormalizer,
publicUrlGenerator or temporaryUrlGenerator service that is not an instance of the class named above.
FlySystem Docs: Visibility, Public URLs, Temporary URLs, Path Traversal
Adapters
Example configs for supported adapters
An option of the wrong type (e.g. 'client' => false) is treated as unset: a required option throws a
MissingConfigException and an optional one falls back to its default. A client or service must
resolve to the class the adapter expects, or an InvalidConfigException is thrown.
Local
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/path/to/root', // Required : Path on local filesystem
'writeFlags' => LOCK_EX, // Optional : PHP flags. See: file_get_contents for more info
'linkBehavior' => \League\Flysystem\Local\LocalFilesystemAdapter::DISALLOW_LINKS, // Optional : Link behavior
// Optional: Optional set of permissions to set for files
'permissions' => [
'file' => [
'public' => 0644,
'private' => 0600,
],
'dir' => [
'public' => 0755,
'private' => 0700,
]
]
],
],
],
],
],
];
FlySystem Docs: Local Adapter
FTP
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'ftp',
'options' => [
'host' => 'ftp.example.com', // Required : Host
'username' => 'username', // Required : Username
'password' => 'password', // Required : Password
'root' => '/root/path/', // required
// optional config settings
'port' => 21,
'ssl' => false,
'timeout' => 90,
'utf8' => false,
'passive' => true,
'transferMode' => FTP_BINARY,
'systemType' => null, // 'windows' or 'unix'
'ignorePassiveAddress' => null, // true or false
'timestampsOnUnixListingsEnabled' => false, // true or false
'recurseManually' => true, // true
],
],
],
],
],
];
FlySystem Docs: FTP
SFTP
Install
composer require league/flysystem-sftp-v3
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'sftp',
'options' => [
'host' => 'example.com', // Required : Host
'port' => 22, // Optional : Port (default: 22)
'username' => 'username', // Required : Username
'password' => 'password', // Optional : Password
'privateKey' => 'path/to/or/contents/of/privatekey', // Optional : Private SSH Key
'passphrase' => 'passphrase', // Optional : SSH Key Passphrase
'root' => '/path/to/root', // Required : Root Path
'timeout' => 10, // Optional : Timeout
'useAgent' => false, // Optional : Use Agent (default: false)
'hostFingerprint' => 'fingerprint', // Optional : Host Fingerprint
'maxTries' => 4, // Optional : Max tries
// Optional: Optional set of permissions to set for files
'permissions' => [
'file' => [
'public' => 0644,
'private' => 0600,
],
'dir' => [
'public' => 0755,
'private' => 0700,
],
],
],
],
],
],
],
];
FlySystem Docs: SFTP
SFTP (phpseclib v2)
For projects that are still on phpseclib v2. New projects should use the SFTP adapter above, which uses phpseclib v3. The two packages can't be installed together.
Install
composer require league/flysystem-sftp
Config
Takes the same options as the SFTP adapter, except that hostFingerprint must be a
string.
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'sftpv2',
'options' => [
'host' => 'example.com', // Required : Host
'port' => 22, // Optional : Port (default: 22)
'username' => 'username', // Required : Username
'password' => 'password', // Optional : Password
'privateKey' => 'path/to/or/contents/of/privatekey', // Optional : Private SSH Key
'passphrase' => 'passphrase', // Optional : SSH Key Passphrase
'root' => '/path/to/root', // Optional : Root Path
'timeout' => 10, // Optional : Timeout
'useAgent' => false, // Optional : Use Agent (default: false)
'hostFingerprint' => 'fingerprint', // Optional : Host Fingerprint
'maxTries' => 4, // Optional : Max tries
'permissions' => [], // Optional : Same as the SFTP adapter
],
],
],
],
],
];
FlySystem Docs: SFTP (phpseclib v2)
Memory
Install
composer require league/flysystem-memory
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'memory',
'options' => [], // No options available
],
],
],
],
];
FlySystem Docs: Memory
Zip Archive
Install
composer require league/flysystem-ziparchive
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'zip',
'options' => [
'path' => '/some/path/to/file.zip' // Required : File name and path to use for zip file
],
],
],
],
],
];
FlySystem Docs: Zip Archive
AWS S3
Note: AWS V2 is not supported in this package
Install
composer require league/flysystem-aws-s3-v3
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 's3',
'options' => [
'client' => 'some-container-service', // Required if client options not provided : S3 client service name
'key' => 'aws-key', // Required if no client provided : Key
'secret' => 'aws-secret', // Required if no client provided : Secret
'region' => 'us-east-1', // Required if no client provided : Region
'bucket' => 'bucket-name', // Required : Bucket Name
'prefix' => 'some/prefix', // Optional : Prefix
'version' => 'latest', // Optional : Api Version. Default: 'latest'
'dirPermissions' => \League\Flysystem\Visibility::PUBLIC, // or ::PRIVATE (Optional)
],
],
],
],
],
];
FlySystem Docs: Aws S3 Adapter - SDK V3
Async Aws S3 Adapter
Install
composer require async-aws/simple-s3
composer require league/flysystem-async-aws-s3
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'AsyncAwsS3',
'options' => [
'client' => 'some-container-service', // Required if client options not provided : S3 client service name
'key' => 'aws-key', // Required if no client provided : Key
'secret' => 'aws-secret', // Required if no client provided : Secret
'region' => 'us-east-1', // Required if no client provided : Region
'bucket' => 'bucket-name', // Required : Bucket Name
'prefix' => 'some/prefix', // Optional : Prefix
'dirPermissions' => \League\Flysystem\Visibility::PUBLIC, // or ::PRIVATE (Optional)
],
],
],
],
],
];
FlySystem Docs: AsyncAws S3 Adapter
Azure Blob Storage
Install
composer require azure-oss/storage-blob-flysystem
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'azureblobstorage',
'options' => [
'container' => 'my-container', // Required : Blob container name
'client' => 'service name', // Required if no connectionString is provided
// Required if no client is provided
'connectionString' => 'DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...',
'prefix' => 'some/path', // Optional : Path prefix
'visibilityHandling' => 'throw', // Optional : 'throw' (default) or 'ignore'
// Optional : Container allows anonymous read access, so public URLs and copies
// use the blob URL instead of a SAS token (default: false)
'isPublicContainer' => false,
],
],
],
],
],
];
Azure Blob Storage has no per-file visibility. By default, setting visibility throws an exception.
Set visibilityHandling to ignore to silently skip it instead. The client service must
be an AzureOss\Storage\Blob\BlobServiceClient.
FlySystem Docs: Azure Blob Storage Adapter
Google Cloud Storage
Install
composer require league/flysystem-google-cloud-storage
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'GoogleCloudStorage',
'options' => [
'bucket' => 'bucket name or service', // Required
'client' => 'service name', // Required if no clientOptions are provided
// Required if no client is provided
'clientOptions' => [
'keyFile' => 'path-to-key-file.json', // Required : Auth key file
'projectId' => 'myProject', // Optional
],
'prefix' => 'some/prefix', // Optional : Prefix
'defaultVisibility' => \League\Flysystem\Visibility::PUBLIC, // or ::PRIVATE (Optional)
// Optional permissions/acl
'permissions' => [
'entity' => 'allUsers',
'publicAcl' => \League\Flysystem\GoogleCloudStorage\PortableVisibilityHandler::ACL_PUBLIC_READ,
'privateAcl' => \League\Flysystem\GoogleCloudStorage\PortableVisibilityHandler::ACL_PRIVATE,
],
],
],
],
],
],
];
FlySystem Docs: Google Cloud Storage Adapter
MongoDB GridFS
Install
Requires the mongodb PHP extension.
pie install mongodb/mongodb-extension
composer require league/flysystem-gridfs
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'gridfs',
'options' => [
'database' => 'my-database', // Required : Database name
'client' => 'service name', // Required if no uri is provided
// Required if no client is provided
'uri' => 'mongodb://localhost:27017',
'bucket' => 'fs', // Optional : GridFS bucket name (default: fs)
'prefix' => 'some/prefix', // Optional : Prefix
],
],
],
],
],
];
The client service must be a MongoDB\Client.
FlySystem Docs: MongoDB GridFS Adapter
WebDAV
Install
composer require league/flysystem-webdav
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'webdav',
'options' => [
// Optional : Service name of a Sabre\DAV\Client in your container.
// When set, the client options below are ignored.
'client' => 'myWebDavClient',
// Client options, used when no client service is set
'baseUri' => 'https://example.com/dav/', // Required : WebDAV server URL
'userName' => 'username', // Optional : Username
'password' => 'password', // Optional : Password
'authType' => \Sabre\DAV\Client::AUTH_BASIC, // Optional : AUTH_BASIC, AUTH_DIGEST and/or AUTH_NTLM
'proxy' => 'proxy.example.com:8080', // Optional : Proxy
'encoding' => \Sabre\DAV\Client::ENCODING_ALL, // Optional : Accepted response encodings
// Adapter options
'prefix' => 'some/path', // Optional : Path prefix
'visibilityHandling' => 'throw', // Optional : 'throw' (default) or 'ignore'
'manualCopy' => false, // Optional : Copy by download and re-upload (default: false)
'manualMove' => false, // Optional : Move by download, re-upload and delete (default: false)
],
],
],
],
],
];
WebDAV has no concept of visibility. By default, setting visibility throws an exception.
Set visibilityHandling to ignore to silently skip it instead. Use manualCopy and
manualMove for servers that don't support the COPY or MOVE methods.
FlySystem Docs: WebDAV Adapter
Decorators
Decorators wrap another adapter to change its behavior. They are configured like any other adapter. The adapter to wrap is either a pre-configured service from the container, the adapter of another filesystem in this config, or a new adapter built from a type and options, exactly like a top level adapter config.
A FlySystem Filesystem service can't be used as the service, since FlySystem doesn't expose
the adapter inside it. To wrap the adapter of a configured filesystem, use filesystem instead.
A new adapter is built from that filesystem's adapter config, so it won't share state with the
original. For the memory adapter, register the adapter as its own container service and use
service.
Path Prefixing
Install
composer require league/flysystem-path-prefixing
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'pathprefixing',
'options' => [
'prefix' => 'some/path', // Required : Path prefix added to every path
'adapter' => [
// Required if no filesystem or type is provided : Service name of a
// League\Flysystem\FilesystemAdapter in your container
'service' => 'myAdapterService',
// Required if no service or type is provided : Name of another
// filesystem in this config whose adapter will be wrapped
'filesystem' => 'other',
// Required if no service or filesystem is provided : Adapter to wrap
'type' => 'local',
'options' => [ // Optional : Options for the wrapped adapter
'root' => '/path/to/root',
],
],
],
],
],
],
],
];
service is used first, then filesystem, then type and options. Paths are prefixed before they reach
the wrapped adapter, and the prefix is removed from paths it returns, for example in listings.
FlySystem Docs: Path Prefixing Adapter
Read-Only
Install
composer require league/flysystem-read-only
Config
<?php
return [
'flysystem' => [
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'readonly',
'options' => [
'adapter' => [
// Required if no filesystem or type is provided : Service name of a
// League\Flysystem\FilesystemAdapter in your container
'service' => 'myAdapterService',
// Required if no service or type is provided : Name of another
// filesystem in this config whose adapter will be wrapped
'filesystem' => 'other',
// Required if no service or filesystem is provided : Adapter to wrap
'type' => 'local',
'options' => [ // Optional : Options for the wrapped adapter
'root' => '/path/to/root',
],
],
],
],
],
],
],
];
service is used first, then filesystem, then type and options. Any write, delete, move, copy or
visibility change throws an exception.
FlySystem Docs: Read-Only Adapter
Mount Manager
The Mount Manager combines several FlySystem services into one, each mounted under a name. It
has its own factory, MountManagerFactory, and is configured under the mounts key. It works
just like FlySystemFactory: the "default" mount is used unless a different mount name is
given.
Each entry in filesystems maps a mount name to the name of a FlySystem service in your
container, usually one created by FlySystemFactory. The mount name is used as the path
scheme, e.g. ftp://path/to/file.
The optional config only accepts visibility and retain_visibility, the two keys the Mount
Manager uses when copying and moving files between mounts. Any other key is ignored.
No extra package is required.
Config
<?php
return [
'dependencies' => [
'factories' => [
// FlySystem services to mount
'fileSystem' => \Blazon\PSR11FlySystem\FlySystemFactory::class,
'ftpFileSystem' => [\Blazon\PSR11FlySystem\FlySystemFactory::class, 'ftp'],
// Mount Manager using the default mount
'defaultMount' => \Blazon\PSR11FlySystem\MountManagerFactory::class,
// Mount Manager using a different mount
'anotherMount' => [\Blazon\PSR11FlySystem\MountManagerFactory::class, 'anotherMount'],
],
],
'flysystem' => [
'mounts' => [
// Array keys are the names used for the mount
'default' => [
// Required : Mount name => FlySystem service name
'filesystems' => [
'local' => 'fileSystem',
'ftp' => 'ftpFileSystem',
],
// Optional : Used when copying and moving files between mounts
'config' => [
'visibility' => \League\Flysystem\Visibility::PRIVATE, // Optional : Visibility::PUBLIC or Visibility::PRIVATE
'retain_visibility' => true, // Optional : Keep visibility (default: true)
],
],
'anotherMount' => [
'filesystems' => [
'local' => 'fileSystem',
],
],
],
'filesystems' => [
'default' => [
'adapter' => [
'type' => 'local',
'options' => [
'root' => '/path/to/root',
],
],
],
'ftp' => [
'adapter' => [
'type' => 'ftp',
'options' => [
'host' => 'ftp.example.com',
'username' => 'username',
'password' => 'password',
'root' => '/root/path/',
],
],
],
],
],
];
Usage
<?php
$mountManager = $container->get('defaultMount');
// Copy a file from the FTP server to the local filesystem
$mountManager->copy('ftp://some/file.txt', 'local://some/file.txt');
It can also be called statically with the mount name, like FlySystemFactory:
$mountManager = \Blazon\PSR11FlySystem\MountManagerFactory::anotherMount($container);
FlySystem Docs: Mount Manager
Upgrades
Version 4 to Version 5
Version 5 upgrades FlySystem to version 3 and requires PHP 8.4 or newer.
Backwards compatibility breaks
PHP 8.4 or newer is required.
FlySystem 3 is required. See the upstream what's new page for changes to the FlySystem API itself.
psr/container1.1 or 2.0 is required.The configuration has been restructured. Each entry now configures a whole FlySystem filesystem, so the
adaptorskey has been renamed tofilesystems, and the adapter'stypeandoptionshave moved into anadapterkey. This leaves room for the new FlySystemconfigand services on each filesystem. See FlySystem Config.Version 4:
'flysystem' => [ 'adaptors' => [ 'default' => [ 'type' => 'local', 'options' => ['root' => '/path/to/root'], ], ], ],Version 5:
'flysystem' => [ 'filesystems' => [ 'default' => [ 'adapter' => [ 'type' => 'local', 'options' => ['root' => '/path/to/root'], ], ], ], ],"Adaptor" has been corrected to "Adapter" everywhere to match FlySystem's spelling.
The
sftpadapter type now uses phpseclib v3. Either:- Replace
league/flysystem-sftpwithleague/flysystem-sftp-v3and keep'type' => 'sftp', or - Stay on phpseclib v2 by keeping
league/flysystem-sftpand changing your config to'type' => 'sftpv2'. See SFTP (phpseclib v2). The options are unchanged, butleague/flysystem-sftpis abandoned upstream, so plan to move to v3.
- Replace
The default port for both SFTP adapters is now
22. It previously defaulted to21, which is the FTP port. Setportexplicitly if you relied on the old default.The default password for both SFTP adapters is now
nullinstead of an empty string.Calling
getContainer()on a container aware factory before a container has been set now throws aMissingServiceExceptioninstead of aTypeError.The Mount Manager now has its own factory,
MountManagerFactory, configured under themountskey. Themanageradapter type shown in the version 4 docs is not supported. See Mount Manager.
Version 2 to Version 3
Version 3 upgrades FlySystem to version 2. FlySystem version 2 is a brand-new take on the great FlySystem. The library has been slim down and simplified. This has caused us to also take a new approach which introduces a number of breaking changes.
Backwards compatibility breaks
Updated all namespaces from WShafer to Blazon as the list of contributors has expanded beyond just myself. This move I believe will help ensure forward compatibility and allow these libraries to stay well maintained well into the future.
The File Manager has been removed. This is a relic of version 1 and was deprecated in version 2. You will need to update your code if you are still using this in your code base.
File Caching has been removed upstream and as a result has been removed from this library as well.
FlySystem plugins have been removed upstream and are no longer supported.
With the removal of caching and plugins the configuration for file systems has been simplified. The "fileSystems" key has been removed and now only the "adapters" key remains.
The "Mount Manager" can now be configured like any other adapter.
Adapters removed upstream:
- Null
- Azure
- Dropbox