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

Doctrine Gaufrette Storable Bundle Laravel Package

ashleydawson/doctrine-gaufrette-storable-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require ashleydawson/doctrine-gaufrette-storable-bundle:0.8.*
    

    Register the bundle in AppKernel.php:

    new AshleyDawson\DoctrineGaufretteStorableBundle\AshleyDawsonDoctrineGaufretteStorableBundle(),
    new Knp\Bundle\GaufretteBundle\KnpGaufretteBundle(), // Required dependency
    
  2. Configure Gaufrette: Add a filesystem adapter in config.yml:

    knp_gaufrette:
        adapters:
            local_adapter:
                local:
                    directory: %kernel.root_dir%/../uploads
        filesystems:
            default:
                adapter: local_adapter
    
  3. Apply the Trait: Use UploadedFileTrait in your Doctrine entity:

    use AshleyDawson\DoctrineGaufretteStorableBundle\Model\UploadedFileTrait;
    
    class Post
    {
        use UploadedFileTrait;
    
        // ... existing fields
    
        public function getFilesystemMapId()
        {
            return 'default'; // Matches your knp_gaufrette config
        }
    }
    
  4. Update Schema:

    php app/console doctrine:schema:update --force
    
  5. First Use Case: Create a form with a file field and bind it to your entity:

    $builder->add('uploaded_file', 'file', ['required' => false]);
    

Implementation Patterns

Workflows

  1. File Upload Handling:

    • Use the trait in entities where files need to be stored (e.g., Product, UserProfile).
    • The trait automatically handles:
      • File metadata (file_name, file_mime_type, file_size).
      • Storage path (file_storage_path).
      • Integration with Gaufrette’s filesystem.
  2. Form Integration:

    • Always name the file field uploaded_file (or proxy via a custom setter).
    • Example:
      $form = $this->createForm(PostType::class, $post);
      $form->handleRequest($request);
      if ($form->isSubmitted() && $form->isValid()) {
          $em->persist($post);
          $em->flush();
      }
      
  3. File Retrieval:

    • Use Gaufrette’s FileSystem service to read files:
      $fileSystem = $this->get('knp_gaufrette.filesystem.default');
      $file = $fileSystem->read($post->getFileStoragePath());
      
  4. Lifecycle Events:

    • Leverage events (e.g., StorageEvents::PRE_WRITE) to customize file paths or metadata:
      $dispatcher->addListener(StorageEvents::PRE_WRITE, function (WriteUploadedFileEvent $event) {
          $event->setFileStoragePath('custom/' . $event->getFileName());
      });
      

Integration Tips

  • Validation: Add constraints to validate file types/sizes:

    use Symfony\Component\Validator\Constraints as Assert;
    
    /**
     * @Assert\File(
     *     maxSize="1024k",
     *     mimeTypes={"image/jpeg", "image/png"}
     * )
     */
    public function getUploadedFile()
    {
        return $this->uploaded_file;
    }
    
  • Symfony 4+: Use autowiring for services (e.g., FilesystemManager):

    public function __construct(private FilesystemManager $filesystemManager) {}
    
  • Testing: Mock UploadedFile and Filesystem in unit tests:

    $uploadedFile = $this->createMock(UploadedFile::class);
    $uploadedFile->method('getClientOriginalName')->willReturn('test.jpg');
    $post->setUploadedFile($uploadedFile);
    

Gotchas and Tips

Pitfalls

  1. Schema Updates:

    • Forgetting to run doctrine:schema:update after adding the trait will cause errors.
    • Fix: Always update the schema in a migration or via CLI.
  2. Filesystem Configuration:

    • Mismatched getFilesystemMapId() and knp_gaufrette config keys will fail silently.
    • Fix: Double-check the config key in getFilesystemMapId().
  3. File Overwrites:

    • The trait does not handle duplicate filenames by default (e.g., two files with image.jpg).
    • Fix: Use StorageEvents::PRE_WRITE to generate unique paths (e.g., UUIDs).
  4. ORM vs. ODM:

    • ODM support is "incomplete" (per README). Use ORM for reliability.
  5. Event Dispatcher:

    • Events are dispatched via Symfony’s EventDispatcher, not Doctrine’s lifecycle callbacks.
    • Fix: Ensure the event_dispatcher service is available (it is by default in Symfony).

Debugging

  • Missing Files:

    • Verify the directory in knp_gaufrette adapters exists and is writable.
    • Check file_storage_path in the database matches the filesystem structure.
  • Validation Errors:

    • Use dump($form->getErrors()) to debug form validation issues.
  • Events Not Triggering:

    • Ensure the listener is registered before the entity lifecycle (e.g., in a controller or command).

Extension Points

  1. Custom Storage Logic:

    • Override the trait’s methods (e.g., setUploadedFile) to add pre-processing:
      public function setUploadedFile(UploadedFile $file = null)
      {
          if ($file) {
              $this->file_name = 'prefix_' . $file->getClientOriginalName();
          }
          parent::setUploadedFile($file);
      }
      
  2. Multiple Files:

    • Extend the trait or create a separate entity for multi-file uploads (e.g., PostImage).
  3. Cloud Storage:

    • Swap the Gaufrette adapter (e.g., aws_s3) without changing entity logic.
  4. Soft Deletes:

    • Use StorageEvents::PRE_DELETE to archive files before "deleting" them:
      $dispatcher->addListener(StorageEvents::PRE_DELETE, function (DeleteUploadedFileEvent $event) {
          $fileSystem->write('archive/' . $event->getFileName(), $event->getFileContent());
      });
      

Config Quirks

  • Caching: Gaufrette caches filesystem configurations. Clear cache (cache:clear) if changes don’t apply.
  • Permissions: Ensure the web server user (e.g., www-data) has write access to the storage directory.
  • Legacy Symfony: The bundle targets Symfony 2.3. For newer versions, test thoroughly or fork the package.
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware