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

Knp Gaufrette Bundle Laravel Package

knplabs/knp-gaufrette-bundle

KnpGaufretteBundle integrates Gaufrette’s filesystem abstraction into Symfony, letting you configure adapters and filesystems as services. It supports local, in-memory, cloud, and custom adapters for storage-agnostic file handling.

View on GitHub
Deep Wiki
Context7

Getting Started

If you are working in a Laravel codebase, this package is not directly installable: it is a Symfony bundle (Knp\Bundle\GaufretteBundle\KnpGaufretteBundle) that registers Gaufrette adapters and filesystems in Symfony’s DI container. In Laravel you would either use the underlying gaufrette/gaufrette library manually, or more commonly use Laravel’s native Storage/Flysystem integration. Treat this assessment as “how would I use this in a Symfony app, and what can I learn from it for my Laravel work?”

In a Symfony app, the minimal path is:

composer require knplabs/knp-gaufrette-bundle
# Install only the adapter packages you actually need, e.g.:
composer require gaufrette/aws-s3-sdk
# or gaufrette/async-aws-s3, gaufrette/ftp, etc.

Register the bundle if Flex does not do it automatically:

// config/bundles.php
return [
    Knp\Bundle\GaufretteBundle\KnpGaufretteBundle::class => ['all' => true],
];

Define an adapter and a filesystem:

# config/packages/knp_gaufrette.yaml
knp_gaufrette:
    adapters:
        uploads_local:
            local:
                directory: '%kernel.project_dir%/var/uploads'

    filesystems:
        uploads:
            adapter: uploads_local
            alias: uploads_filesystem

The filesystem becomes a service named gaufrette.uploads_filesystem, with the alias uploads_filesystem for autowiring. Inject Gaufrette\Filesystem into a service:

use Gaufrette\Filesystem;

final class AvatarStorage
{
    public function __construct(private Filesystem $uploadsFilesystem) {}

    public function store(string $key, string $contents): void
    {
        $this->uploadsFilesystem->write($key, $contents, true);
    }
}

Where to look first:

  • README.md for adapter/filesystem config shape.
  • Resources/docs/adapters/*.md for the exact config keys of each adapter.
  • Resources/docs/use-case-examples.md for basic read/write examples.
  • DependencyInjection/Configuration.php in the bundle source when documentation and reality disagree.
  • The Gaufrette library docs for the actual Filesystem API (read, write, delete, has, keys, mtime, etc.).

A good first use case is environment-parity uploads: local adapter in dev/test, S3 adapter in prod, with the same filesystem alias in application code.

Implementation Patterns

One filesystem per storage concern. Define separate filesystems for avatars, documents, exports, etc. This keeps bucket/path configuration isolated and lets you swap one storage backend without touching the others.

Autowire by alias for normal services. The alias option is the cleanest integration point. Inject Gaufrette\Filesystem where there is exactly one filesystem for that service. Use a named alias or a small wrapper service if you have multiple filesystems and need to avoid ambiguous autowiring.

Use the filesystem map for dynamic selection. When the backend is chosen at runtime (tenant, customer tier, region):

use Gaufrette\FilesystemMap;

final class TenantFileLocator
{
    public function __construct(private FilesystemMap $filesystemMap) {}

    public function forTenant(string $tenant): \Gaufrette\Filesystem
    {
        return $this->filesystemMap->get($tenant === 'enterprise' ? 'premium' : 'standard');
    }
}

The map service is knp_gaufrette.filesystem_map. Prefer injectable wrappers over $container->get(...) calls in application code.

Environment-specific adapter configuration. Keep the filesystem name stable and switch the adapter implementation per environment:

# config/packages/knp_gaufrette.yaml
knp_gaufrette:
    adapters:
        uploads_adapter:
            local:
                directory: '%kernel.project_dir%/var/uploads'

# config/packages/prod/knp_gaufrette.yaml
knp_gaufrette:
    adapters:
        uploads_adapter:
            aws_s3:
                service_id: 'app.s3_client'
                bucket_name: '%env(S3_BUCKET)%'

This is the main day-to-day value: application services never know whether files live on disk, S3, FTP, or Azure.

Wrap third-party clients as services. Most cloud adapters accept a service_id for an existing SDK client. Define that client as a Symfony service with credentials from environment variables, then point the adapter at it. Avoid hardcoding credentials in the Gaufrette config.

Use the cache adapter deliberately. For read-heavy remote storage, a cache adapter can sit in front of S3/FTP. Treat it as a read cache only: plan invalidation when files are overwritten or deleted, and do not assume it makes writes faster or atomic.

Keep upload orchestration in your own service. Gaufrette gives you write, read, delete, and has, but not validation, virus scanning, image resizing, or database metadata. A typical flow is: validate upload, generate a UUID-based key, write to Gaufrette, persist the key/metadata in Doctrine, and delete the old file after a successful transaction.

Testing pattern. Use the in-memory adapter in config/packages/test/knp_gaufrette.yaml so tests do not touch S3 or the local disk:

knp_gaufrette:
    adapters:
        uploads_adapter:
            in_memory: ~

For adapter-specific behavior (S3 ACLs, FTP permissions), use LocalStack or a disposable test bucket rather than unit tests.

Stream wrapper for legacy code. The bundle supports a stream wrapper adapter, which can help when third-party code expects fopen/file_get_contents. Use it as a compatibility bridge, not as the primary API.

Laravel translation. If you like this abstraction in Laravel, do not try to register the bundle. Either instantiate Gaufrette filesystems in a service provider, or use Laravel’s Storage facade, which already provides a Flysystem-backed abstraction. The architectural lesson — inject a storage abstraction, not a concrete SDK — transfers directly.

Gotchas and Tips

  • Adapters are separate packages. Installing only knplabs/knp-gaufrette-bundle will not give you S3, FTP, Azure, or Google Cloud support. Install the matching gaufrette/* adapter package, otherwise container compilation fails with an unknown adapter type.
  • Config keys differ per adapter. The top-level shape is consistent, but each adapter has its own keys (directory, bucket_name, service_id, region, detect_content_type, etc.). Always check the adapter doc page; copy-pasting between adapters is a common source of “unrecognized option” errors.
  • Service IDs and aliases are not the same. The filesystem service is gaufrette.<name>_filesystem; the alias option creates an additional alias. Autowiring works via the alias, not necessarily the internal service ID. Use bin/console debug:container gaufrette and bin/console debug:config knp_gaufrette when injection fails.
  • Clear the container cache after config changes. Symfony compiles bundle configuration into the container. Stale config cache is a frequent cause of “my new adapter does not exist” confusion.
  • Version constraints matter. v0.8.0 introduced typed signatures and is a BC break if you extended bundle classes. v0.9.0 added Symfony 7 support and dropped Symfony 4. Check your Symfony and PHP versions before upgrading.
  • Gaufrette’s API is not Flysystem’s API. write() returns the number of bytes written, not a boolean. Overwrite behavior is explicit (write($key, $contents, true)), and keys()/listing behavior varies by adapter. Do not build cross-adapter logic on undocumented metadata.
  • Large files are a concern. The basic Gaufrette API returns file contents as strings. For multi-gigabyte uploads or streaming downloads, verify adapter support and consider handing large-object transfers to the cloud SDK directly.
  • Remote storage is not a local filesystem. Renames, atomic writes, directory semantics, permissions, and consistency differ across S3, FTP, and local adapters. Do not assume rename() or keys() behaves identically everywhere.
  • S3 configuration is especially error-prone. Region, endpoint, path-style addressing, ACLs, and content-type detection are common failure points. Modern projects should prefer the async-aws adapter over the legacy AWS SDK adapter where possible.
  • Do not expose filesystem errors directly to users. Wrap Gaufrette\Exception\* exceptions in domain exceptions, log the adapter/key, and return a generic upload failure to the UI.
  • Use safe_local for user-controlled paths. The plain local adapter does not protect against path traversal; the safe local adapter is the right choice when keys are derived from user input.
  • Debugging tips. Use debug:container --tag=..., lint:container, and a small command or test that writes/reads/deletes a probe file. For cloud issues, test the underlying SDK client service independently of Gaufrette to isolate credentials/network problems from bundle configuration.
  • Extension point: custom adapters. If no adapter fits, implement a Gaufrette adapter and register it via the service adapter configuration. This is the clean escape hatch; avoid forking the bundle for one-off storage backends.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource