devture/symfony-storer-bundle
Install the Bundle
composer require devture/symfony-storer-bundle
Add to config/bundles.php:
Devture\Bundle\StorerBundle\DevtureStorerBundle::class => ['all' => true],
Configure Storage
Add to config/packages/devture_storer.yaml:
devture_storer:
adapter_url: '%env(resolve:DEVTURE_STORER_ADAPTER_URL)%'
validation_max_size_megabytes: 20 # Optional: Set file size limits
Define .env (e.g., for local filesystem):
DEVTURE_STORER_ADAPTER_URL=local:///path/to/storage
Or for S3:
DEVTURE_STORER_ADAPTER_URL=s3://bucket-name?key=YOUR_ACCESS_KEY&secret=YOUR_SECRET_KEY®ion=us-east-1
First Use Case: Upload a File
Inject the StorerInterface into a service/controller:
use Devture\Bundle\StorerBundle\Storer\StorerInterface;
public function uploadFile(UploadedFile $file, StorerInterface $storer)
{
$storer->store($file, 'unique_filename.ext');
}
Storing Files
// Store an UploadedFile
$storer->store($uploadedFile, 'path/to/file.ext');
// Store raw content
$storer->storeFromString('Hello, world!', 'file.txt');
Retrieving Files
// Get file contents
$content = $storer->read('path/to/file.ext');
// Stream a file (useful for large files)
$stream = $storer->readStream('path/to/file.ext');
Deleting Files
$storer->delete('path/to/file.ext');
Checking Existence
if ($storer->has('path/to/file.ext')) {
// File exists
}
use Symfony\Component\Form\Extension\Core\Type\FileType;
// In a form builder
$builder->add('file', FileType::class, [
'mapped' => false,
'constraints' => [
new File\FileType('image/jpeg'),
new File\MaxSize('20M'),
],
]);
// Handle submission
public function onSubmit(UploadedFile $file, StorerInterface $storer)
{
$storer->store($file, 'uploads/' . uniqid() . '.' . $file->guessExtension());
}
// List files in a directory
$files = $storer->listContents('path/to/directory');
// Delete multiple files
foreach ($files as $file) {
$storer->delete($file->getPathname());
}
Extend AdapterFactory to support unsupported providers (e.g., Backblaze B2):
// In Helper/AdapterFactory.php (or a custom service)
public function createAdapterFromUrl($url)
{
if (str_starts_with($url, 'b2://')) {
return new \Gaufrette\Adapter\B2Adapter(...);
}
// ... existing logic
}
URL Encoding Secrets
secret=pass%2Fword).rawurlencode() or Symfony’s %env(resolve:VAR)% with urlencode filter:
adapter_url: '%env(resolve:DEVTURE_STORER_ADAPTER_URL|urlencode)%'
File Validation
validation_max_size_megabytes), but no MIME-type validation by default.File constraint for validation:
use Symfony\Component\Validator\Constraints\File;
$constraints = new File([
'maxSize' => '20M',
'mimeTypes' => ['image/jpeg', 'image/png'],
]);
Permissions
www-data) has write permissions:
chown -R www-data:www-data /path/to/storage
chmod -R 755 /path/to/storage
CORS for Remote Storage
Symlink Handling
Gaufrette\Adapter\SymlinkedAdapter if needed:
$adapter = new \Gaufrette\Adapter\SymlinkedAdapter($originalAdapter);
Check Adapter Creation
adapter_url to verify configuration:
$container->getParameter('devture_storer.adapter_url');
Enable Gaufrette Debugging
GAUFRETTE_DEBUG in .env to log adapter operations:
GAUFRETTE_DEBUG=1
Test Locally Before Deploying
local:// for development, then switch to s3:// or azure:// in production.Custom Metadata
StorerInterface to add metadata (e.g., getMetadata()):
interface CustomStorerInterface extends StorerInterface {
public function getMetadata(string $pathname): array;
}
Event Listeners
$dispatcher->dispatch(new FileStoredEvent($filePath, $storer));
Fallback Adapters
$primaryAdapter = $storer->getAdapter();
$fallbackAdapter = new \Gaufrette\Filesystem(new \Gaufrette\Adapter\Local($localPath));
if (!$primaryAdapter->has($path)) {
$fallbackAdapter->write($path, $primaryAdapter->read($path));
}
Async Operations
$message = new StoreFileMessage($file, $path);
$bus->dispatch($message);
How can I help you explore Laravel packages today?