Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Flysystem Openstack Swift Laravel Package

nimbusoft/flysystem-openstack-swift

Flysystem adapter for OpenStack Swift object storage. Mount Swift containers as filesystems in Laravel/PHP apps and read, write, list, or delete objects through Flysystem’s unified API. Configure auth URL, region, container, and credentials, then use it like any other Laravel disk.

View on GitHub
Deep Wiki
Context7

Getting Started

This adapter bridges Flysystem's filesystem API to OpenStack Swift object storage via php-opencloud/openstack. It is not a Laravel package — no service provider, no config file, no facade — so day-one setup is: install, wire the OpenStack client, wrap the container.

1. Install

composer require nimbusoft/flysystem-openstack-swift

Check composer.json first: the adapter ships major versions aligned to Flysystem (^1.0 for Flysystem 1, ^2.0/^3.0 for Flysystem 3). Confirm the OpenStack SDK constraint (php-opencloud/openstack) is pulled in — if not, require it explicitly so you control the version.

2. Where to look first

  • README.md on GitHub — the only documentation; covers adapter construction and basic usage.
  • src/OpenStackSwiftAdapter.php — the single class you actually depend on. Read it before integrating; it tells you exactly which Flysystem v3 FilesystemAdapter methods are implemented and how paths map to Swift object keys.
  • composer.json — release date (Feb 2023), supported PHP versions, and Flysystem/SDK constraints.
  • vendor/nimbusoft/flysystem-openstack-swift/tests/ if they're shipped — the tests double as usage examples.

3. First use case: read/write a blob

use OpenStack\OpenStack;
use Nimbusoft\Flysystem\OpenStackSwift\OpenStackSwiftAdapter;
use League\Flysystem\Filesystem;
use League\Flysystem\MountManager;

$openStack = new OpenStack([
    'authUrl' => env('OS_AUTH_URL'),          // e.g. https://identity.example.com/v3
    'region'  => env('OS_REGION'),
    'user'    => [
        'name'     => env('OS_USERNAME'),
        'password' => env('OS_PASSWORD'),
        'domain'   => ['id' => 'default'],
    ],
    'scope' => [
        'project' => [
            'name'   => env('OS_PROJECT_NAME'),
            'domain' => ['id' => 'default'],
        ],
    ],
]);

$container = $openStack->objectStoreV1()->getContainer(env('OS_CONTAINER'));

$adapter    = new OpenStackSwiftAdapter($container);
$filesystem = new Filesystem($adapter);

$filesystem->write('reports/2024/q1.pdf', file_get_contents($pdfPath), [
    'mimetype' => 'application/pdf',
]);

$stream = $filesystem->readStream('reports/2024/q1.pdf');

That's the whole loop: authenticate → fetch container → adapter → Filesystem. Everything else (listing, deletes, visibility) goes through the standard Flysystem API.

Implementation Patterns

Laravel disk registration (the most common integration). Laravel's Storage facade expects a Flysystem-backed disk. Register the driver once in a service provider:

// app/Providers/AppServiceProvider.php  (boot)
use Illuminate\Support\Facades\Storage;
use League\Flysystem\Filesystem;
use OpenStack\OpenStack;
use Nimbusoft\Flysystem\OpenStackSwift\OpenStackSwiftAdapter;

Storage::extend('swift', function ($app, array $config) {
    $openStack = new OpenStack([
        'authUrl' => $config['authUrl'],
        'region'  => $config['region'],
        'user'    => [
            'name'     => $config['username'],
            'password' => $config['password'],
            'domain'   => ['id' => $config['domain'] ?? 'default'],
        ],
        'scope' => [
            'project' => [
                'name'   => $config['project'],
                'domain' => ['id' => $config['domain'] ?? 'default'],
            ],
        ],
    ]);

    $container = $openStack->objectStoreV1()->getContainer($config['container']);

    return new Filesystem(new OpenStackSwiftAdapter($container));
});
// config/filesystems.php
'swift' => [
    'driver'    => 'swift',
    'authUrl'   => env('OS_AUTH_URL'),
    'region'    => env('OS_REGION'),
    'username'  => env('OS_USERNAME'),
    'password'  => env('OS_PASSWORD'),
    'project'   => env('OS_PROJECT_NAME'),
    'container' => env('OS_CONTAINER'),
],

Then Storage::disk('swift')->put('avatars/me.jpg', $contents) works everywhere in the app.

Bind the OpenStack client as a singleton. Auth is the expensive part of the round trip. Constructing new OpenStack(...) per request is acceptable (it's lazy), but binding a shared client / pre-built Container object in the container avoids repeated auth handshakes in long-running processes (queues, Octane):

$this->app->singleton(OpenStackSwiftAdapter::class, function ($app) {
    $openStack = new OpenStack(config('services.swift'));
    return new OpenStackSwiftAdapter($openStack->objectStoreV1()->getContainer(config('services.swift.container')));
});

Prefix-based multi-tenancy. Swift has no directory hierarchy; "folders" are just / in object keys. Use a per-tenant prefix and keep it in one place:

$filesystem->write("tenants/{$tenantId}/invoices/{$id}.pdf", $pdf);

Do not rely on createDirectory() for isolation. Treat prefixes as the contract, and never assume a directory exists because the adapter "created" one.

Pair with CacheAdapter for read-heavy workloads. Every listContents or fileExists hits Swift. Wrapping the adapter in League\Flysystem\Cached\Storage\... / CacheAdapter is the standard Flysystem trick and usually the single biggest latency win:

$adapter = new \League\Flysystem\Cached\CachedAdapter(
    new OpenStackSwiftAdapter($container),
    new \League\Flysystem\Cached\Storage\Memory()
);

Testing pattern. Run a local Swift (e.g. openstack-swift in Docker, or the swift container in a devstack) and point OS_AUTH_URL at it. Because Swift is flat and containers are cheap, use a unique container per test class (phpunit-{uuid}), create it via the SDK in setUp, and delete it in tearDown. That keeps the adapter's list/read/write behavior under test without mocking the SDK.

Gotchas and Tips

  • Version pinning is the primary risk. Flysystem had a breaking v1 → v3 adapter interface change, and this package's majors track that. A composer require that pulls Flysystem 3 with a 1.x adapter (or vice versa) fails at runtime with an interface-mismatch error, not at install time. Pin both: "league/flysystem": "^3.0" and "nimbusoft/flysystem-openstack-swift": "^3.0" (adjust to what composer show reports).

  • No container auto-creation. The adapter takes an already-fetched Container object. If you pass a container name that doesn't exist, you get an SDK exception during construction, not a clean Flysystem error. Create containers out-of-band (SDK or openstack object create) in your provisioning step.

  • Swift is flat; Flysystem "directories" are a fiction. listContents($path, true) uses the delimiter=/ prefix/delimiter trick. Consequences: directory listings are eventually consistent on some Swift backends, deleteDirectory must enumerate and delete each object (slow for large trees), and creating an empty "folder" may be a no-op or a zero-byte placeholder depending on the adapter implementation. Never build logic that depends on an empty directory surviving.

  • Visibility is container-level, not object-level. In Swift, public access is controlled by the container's X-Container-Read ACL, not per-object ACLs (object-level ACLs exist but the adapter likely ignores them). setVisibility(..., 'public') may succeed while having no real effect. For genuinely public assets, either set the container ACL to .r:* and generate URLs like {storage-url}/{container}/{key}, or use Swift temp URLs ($container->getObject($key)->getTemporaryUrl()) for private content. Laravel's Storage::url() will not work out of the box — the adapter doesn't implement a URL generator.

  • mimetype and metadata options are limited. Flysystem passes a config array to write; the adapter maps a subset (mimetype, and on some versions Cache-Control/Content-Disposition are not supported). Verify in OpenStackSwiftAdapter::write() which keys actually get forwarded to the Swift Object options. If you need Content-Disposition for downloads, drop to the SDK directly rather than fighting the adapter.

  • Debugging auth/network failures. php-opencloud/openstack builds a Guzzle client. Add a debug middleware to see every request/response; 401s are usually a missing domain.id in the user or scope block (v3 auth requires it), and 404s on getContainer are almost always a wrong region or project scope. region mismatches surface as "container not found," which is misleading — check objectStoreV1() endpoints first.

  • Streams and large files. writeStream/readStream go through Guzzle; very large uploads may buffer depending on SDK behavior. For multi-GB objects, prefer the Swift SDK's segmented upload directly, or at minimum benchmark memory before adopting the adapter for backups/media.

  • Errors are Flysystem exceptions. Expect UnableToReadFile, UnableToWriteFile, UnableToDeleteFile, UnableToSetVisibility (all in League\Flysystem\*). Catch those at your application boundary; let OpenStack\Common\Error\BadResponseError bubble only if you want SDK-level detail.

  • Maintenance posture. 43 stars, 0 dependents, single last release in Feb 2023, and one active maintainer. Treat the adapter as a thin, forkable shim: keep the adapter construction behind a small factory class of your own so a future fork or replacement (Laravel's first-party league/flysystem-aws-s3-v3 won't help — Swift-specific) is a one-file change. Extension points are limited to subclassing OpenStackSwiftAdapter (override write/listContents to add metadata or path rewriting) or wrapping the Container SDK object before handing it in. There are no config hooks or plugin interfaces.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator