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

Uploader Bundle Laravel Package

vich/uploader-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require vich/uploader-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        Vich\UploaderBundle\VichUploaderBundle::class => ['all' => true],
    ];
    
  2. Configure Storage: Add to config/packages/vich_uploader.yaml:

    vich_uploader:
        db_driver: orm  # or 'mongodb', 'phpcr'
        storage: vich_uploader.storage.local_directory
        mappings:
            products:
                uri_prefix: /uploads/products
                upload_destination: '%kernel.project_dir%/public/uploads/products'
                namer: Vich\UploaderBundle\Naming\SmartUniqueNamer
    
  3. First Use Case: Create an entity with uploadable fields:

    use Vich\UploaderBundle\Mapping\Annotation as Vich;
    
    #[ORM\Entity]
    class Product
    {
        #[Vich\UploadableField(mapping: 'products', fileNameProperty: 'imageName')]
        private ?File $imageFile = null;
    
        #[ORM\Column(length: 255)]
        private ?string $imageName = null;
    
        // Getters/setters...
    }
    
  4. Form Integration:

    {{ form_start(form) }}
        {{ form_widget(form.imageFile) }}
        {{ form_widget(form.submit) }}
    {{ form_end(form) }}
    
  5. Access Uploaded File:

    $product->getImagePath(); // Returns public URL
    

Implementation Patterns

Common Workflows

1. Basic File Upload

  • Use #[Vich\UploadableField] on entity properties.
  • Configure upload_destination and uri_prefix in vich_uploader.yaml.
  • Handle file deletion via lifecycle callbacks:
    #[ORM\PreRemove]
    public function preRemove(): void
    {
        if ($this->imageFile) {
            $this->imageFile->delete();
        }
    }
    

2. Dynamic Upload Directories

  • Use getUploadDir() in your entity:
    public function getUploadDir(): string
    {
        return 'uploads/products/' . $this->category->id;
    }
    

3. Custom Naming Strategies

  • Implement Vich\UploaderBundle\Naming\NamerInterface:
    class CustomNamer implements NamerInterface
    {
        public function name(File $file): string
        {
            return 'custom_' . uniqid() . '.' . $file->guessExtension();
        }
    }
    
  • Register in services.yaml:
    services:
        App\Naming\CustomNamer:
            tags: ['vich_uploader.namer']
    

4. Form Integration with Validation

  • Use Vich\UploaderBundle\Form\Type\VichFileType:
    $builder->add('imageFile', VichFileType::class, [
        'required' => false,
        'allow_delete' => true,
        'download_uri' => true,
    ]);
    
  • Add validation constraints:
    use Vich\UploaderBundle\Validator\Constraints as VichAssert;
    
    #[VichAssert\FileMaxSize(maxSize: '1M')]
    #[VichAssert\FileMimeType(type: 'image/jpeg')]
    private ?File $imageFile = null;
    

5. Handling Multiple Files

  • Use #[Vich\UploadableField(mapping: 'products', fileNameProperty: 'images')] with a Collection or ArrayCollection:
    #[ORM\Column(length: 255, nullable: true)]
    private ?string $images = null;
    
    #[Assert\All({
        new Assert\FileMaxSize(maxSize: '5M'),
        new Assert\FileMimeType(type: 'image/*')
    })]
    private array $imagesFiles = [];
    

6. Asynchronous Processing

  • Use Symfony Messenger to process uploads in the background:
    use Vich\UploaderBundle\Message\UploadHandler;
    
    $message = new UploadHandler($entity, $propertyName);
    $this->messageBus->dispatch($message);
    

7. Cloud Storage (e.g., AWS S3)

  • Configure vich_uploader.storage to use vich_uploader.storage.flysystem:
    vich_uploader:
        storage: vich_uploader.storage.flysystem
        db_driver: orm
        mappings:
            products:
                uri_prefix: /uploads/products
    
  • Set up FlySystem adapter in services.yaml:
    services:
        vich_uploader.storage.flysystem:
            class: Vich\UploaderBundle\Storage\FlysystemStorage
            arguments:
                - '@oneup_flysystem.aws_s3.vich_storage'
    

Integration Tips

1. Symfony Forms

  • Use VichFileType for file inputs:
    {{ form_widget(form.imageFile, {
        'attr': {
            'class': 'custom-upload-class',
            'data-upload-url': path('app_upload')
        }
    }) }}
    

2. API Endpoints

  • Handle file uploads via API:
    #[Route('/upload', name: 'app_upload', methods: ['POST'])]
    public function upload(Request $request, UploadHandler $handler): JsonResponse
    {
        $data = json_decode($request->getContent(), true);
        $entity = new Product();
        $entity->setImageFile($request->files->get('imageFile'));
    
        $handler->handle($entity, 'imageFile');
        $em->persist($entity);
        $em->flush();
    
        return new JsonResponse(['success' => true]);
    }
    

3. Image Processing

  • Integrate with LiipImagineBundle for image resizing:
    vich_uploader:
        db_driver: orm
        mappings:
            products:
                uri_prefix: /uploads/products
                namer: Vich\UploaderBundle\Naming\SmartUniqueNamer
                injections:
                    image_file: liip_imagine_filter
    
    #[Vich\UploadableField(mapping: 'products', fileNameProperty: 'imageName')]
    #[Assert\Image]
    private ?File $imageFile = null;
    

4. Event Listeners

  • Listen to upload events for custom logic:
    use Vich\UploaderBundle\Event\Event;
    use Vich\UploaderBundle\Event\Events;
    
    $dispatcher->addListener(Events::PRE_UPLOAD, function (Event $event) {
        $file = $event->getFileObject();
        // Custom logic before upload
    });
    

5. Testing

  • Use Vich\UploaderBundle\Test\IntegrationTestTrait for tests:
    use Vich\UploaderBundle\Test\IntegrationTestTrait;
    
    class ProductTest extends WebTestCase
    {
        use IntegrationTestTrait;
    
        public function testUpload(): void
        {
            $client = static::createClient();
            $crawler = $client->request('GET', '/product/new');
    
            $form = $crawler->selectButton('Save')->form([
                'product[imageFile]' => __DIR__ . '/fixtures/test.jpg',
            ]);
    
            $client->submit($form);
            $this->assertResponseIsSuccessful();
        }
    }
    

Gotchas and Tips

Pitfalls and Debugging

1. File Not Uploading

  • Cause: Missing fileNameProperty in #[Vich\UploadableField] or incorrect upload_destination.
  • Fix: Ensure the property exists and is mapped correctly:
    #[Vich\UploadableField(mapping: 'products', fileNameProperty: 'imageName')]
    private ?File $imageFile = null;
    
    #[ORM\Column(length: 255, nullable: true)]
    private ?string $imageName = null;
    

2. Permission Issues

  • Cause: Incorrect permissions on upload_destination.
  • Fix: Set proper permissions:
    chmod -R 775 %kernel.project_dir%/public/uploads
    

3. File Not Deleting on Entity Removal

  • Cause: Missing lifecycle callback or #[ORM\PreRemove].
  • Fix: Add the callback:
    #[ORM\PreRemove]
    public function preRemove(): void
    {
        if ($this->imageFile) {
            $this->imageFile->delete();
        }
    }
    

4. Double File Uploads

  • Cause: Form submitted twice or missing #[Assert\Valid] on entity.
  • Fix: Add validation to your form:
    $builder->addEvent
    
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.
phalcon/cli-options-parser
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
directorytree/privacy-filter-classifier
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata