Search by

blazon / psr11-flysystem

wshafer

Flysystem Factories for PSR-11

Package info

gitlab.com/blazon/psr11-flysystem

Issues

pkg:composer/blazon/psr11-flysystem

Statistics

Installs: 8 982

Dependents: 0

Suggesters: 0

Stars: 0

5.0.0-RC3 2026-10-09 18:29 UTC

This package is auto-updated.

Last update: 2026-10-10 01:41:39 UTC


README

codecov pipeline status

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/container 1.1 or 2.0 is required.

  • The configuration has been restructured. Each entry now configures a whole FlySystem filesystem, so the adaptors key has been renamed to filesystems, and the adapter's type and options have moved into an adapter key. This leaves room for the new FlySystem config and 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 sftp adapter type now uses phpseclib v3. Either:

    • Replace league/flysystem-sftp with league/flysystem-sftp-v3 and keep 'type' => 'sftp', or
    • Stay on phpseclib v2 by keeping league/flysystem-sftp and changing your config to 'type' => 'sftpv2'. See SFTP (phpseclib v2). The options are unchanged, but league/flysystem-sftp is abandoned upstream, so plan to move to v3.
  • The default port for both SFTP adapters is now 22. It previously defaulted to 21, which is the FTP port. Set port explicitly if you relied on the old default.

  • The default password for both SFTP adapters is now null instead of an empty string.

  • Calling getContainer() on a container aware factory before a container has been set now throws a MissingServiceException instead of a TypeError.

  • The Mount Manager now has its own factory, MountManagerFactory, configured under the mounts key. The manager adapter 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