Weave Code
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

Symfony Storer Bundle Laravel Package

devture/symfony-storer-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle

    composer require devture/symfony-storer-bundle
    

    Add to config/bundles.php:

    Devture\Bundle\StorerBundle\DevtureStorerBundle::class => ['all' => true],
    
  2. 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&region=us-east-1
    
  3. 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');
    }
    

Implementation Patterns

Core Workflows

  1. Storing Files

    // Store an UploadedFile
    $storer->store($uploadedFile, 'path/to/file.ext');
    
    // Store raw content
    $storer->storeFromString('Hello, world!', 'file.txt');
    
  2. 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');
    
  3. Deleting Files

    $storer->delete('path/to/file.ext');
    
  4. Checking Existence

    if ($storer->has('path/to/file.ext')) {
        // File exists
    }
    

Integration with Symfony Forms

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());
}

Batch Operations

// List files in a directory
$files = $storer->listContents('path/to/directory');

// Delete multiple files
foreach ($files as $file) {
    $storer->delete($file->getPathname());
}

Custom Adapters

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
}

Gotchas and Tips

Common Pitfalls

  1. URL Encoding Secrets

    • For remote adapters (e.g., S3), URL-encode secrets (e.g., secret=pass%2Fword).
    • Use rawurlencode() or Symfony’s %env(resolve:VAR)% with urlencode filter:
      adapter_url: '%env(resolve:DEVTURE_STORER_ADAPTER_URL|urlencode)%'
      
  2. File Validation

    • The bundle validates file size (configurable via validation_max_size_megabytes), but no MIME-type validation by default.
    • Use Symfony’s File constraint for validation:
      use Symfony\Component\Validator\Constraints\File;
      
      $constraints = new File([
          'maxSize' => '20M',
          'mimeTypes' => ['image/jpeg', 'image/png'],
      ]);
      
  3. Permissions

    • For local storage, ensure the web server user (e.g., www-data) has write permissions:
      chown -R www-data:www-data /path/to/storage
      chmod -R 755 /path/to/storage
      
  4. CORS for Remote Storage

    • If using S3/Azure with a CDN, configure CORS rules separately (not handled by this bundle).
  5. Symlink Handling

    • Gaufrette (underlying library) does not follow symlinks by default. Use Gaufrette\Adapter\SymlinkedAdapter if needed:
      $adapter = new \Gaufrette\Adapter\SymlinkedAdapter($originalAdapter);
      

Debugging Tips

  1. Check Adapter Creation

    • Log the resolved adapter_url to verify configuration:
      $container->getParameter('devture_storer.adapter_url');
      
  2. Enable Gaufrette Debugging

    • Set GAUFRETTE_DEBUG in .env to log adapter operations:
      GAUFRETTE_DEBUG=1
      
  3. Test Locally Before Deploying

    • Use local:// for development, then switch to s3:// or azure:// in production.

Extension Points

  1. Custom Metadata

    • Extend StorerInterface to add metadata (e.g., getMetadata()):
      interface CustomStorerInterface extends StorerInterface {
          public function getMetadata(string $pathname): array;
      }
      
  2. Event Listeners

    • Dispatch events before/after file operations using Symfony’s event system:
      $dispatcher->dispatch(new FileStoredEvent($filePath, $storer));
      
  3. Fallback Adapters

    • Implement a fallback chain (e.g., try S3, fall back to local):
      $primaryAdapter = $storer->getAdapter();
      $fallbackAdapter = new \Gaufrette\Filesystem(new \Gaufrette\Adapter\Local($localPath));
      
      if (!$primaryAdapter->has($path)) {
          $fallbackAdapter->write($path, $primaryAdapter->read($path));
      }
      
  4. Async Operations

    • Use Symfony Messenger to queue file operations (e.g., for large uploads):
      $message = new StoreFileMessage($file, $path);
      $bus->dispatch($message);
      
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope