1
votes

I have a form type that I use for making a reusable form for uploading a file. It's integrated with Gaufrette and Amazon S3, and works like a charm. I wanted to reuse the same form type for editing / updating.

I created the routing, callback, etc. for the edit. When I reuse the same form type, it breaks on the mapping:

The form's view data is expected to be an instance of class Symfony\Component\HttpFoundation\File\File, but is a(n) string. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) string to an instance of Symfony\Component\HttpFoundation\File\File.

When I set mapped to false, the form works for update, but doesn't work for the initial creation.

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('name')
        ->add('path', 'file', array('mapped' => false))
        ->add('report')
    ;
}

It seems like the path that's being saved is not able to be mapped to the form, and my work around was to have two form types for upload and creation, but that didn't seem like the right approach.

What's the best way to do this?

1
I've still been using two forms, one for editing, and one for creating, and I think this is the best approach.Foo

1 Answers

0
votes

The symfony cookbock on this topic advocates the use of two seperate fields on the entity. One being the path and the other a file (of typeUploadedFile actually).

So it is by-the book and perfectly fine.

The file field is not being persisted (that means it's not in Entity.orm.yml, or has @ORM Annotations). After your controller handled the request, you call a upload function on the entity (which is bad code design*) which moves the file from e.g. /tmp/php to the web folder of your application and updates the path attribute of your entity respectively.

Snippet (update or create action of your controller):

$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if($form->isValid()) {
    if( null !== $entity->getFile() ) {
        $entity->upload();
    }
    $em->persist($entity);//Only when in createAction
    $em->flush();
}

Regardless wether you use doctrine or not you will get the idea: http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html

*You should extract that logic into a seperate symfony service