I'm trying implement file uploading functionality for my app with Symfony 3. I have a product entiry, that have relation to File entiry. Part of Product:
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\File", mappedBy="product")
* @ORM\OrderBy({"weight" = "DESC"})
*/
protected $files;
and field on form:
->add('files', FileType::class, array('multiple'=> true, 'data_class'=> 'AppBundle\Entity\File'));
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Product',
));
}
As you can see, I'm set data_class.
and in controller I'm trying handle form
public function addAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$product = new Product();
$product->setAddedBy($this->getUser());
$form = $this->createForm(ProductType::class, null);
$form->handleRequest($request);
...
and I have an error:
Expected argument of type "AppBundle\Entity\File", "Symfony\Component\HttpFoundation\File\UploadedFile" given
If I drop data_class mapping I have no error and no object, just array. How I can resolve this error, how to transform UploadedFile to File (Entiry). I'm trying to create Transformer, but I just got the ProductEntiry class, and as result can't process it, becouse it's without files.
Before I'll get to the point, just one suggest. In line:
$form = $this->createForm(ProductType::class, null);
I would provide $product
variable so it will be automatically filled with data instead of creating new one. So it should be changed to :
$form = $this->createForm(ProductType::class, $product);
Ok, now, the problem occurs, because you probably have in your Product
class a setter like:
public function addFile(AppBundle\Entity\File $file) { ... }
Then, after successful validation, the form tries to fill instance of Product
class with data from the form, which contains Symfony's UploadedFile
class instance. I hope you understand that.
Now, you have (at least) two possible solutions.
You can set "mapped" => false
option for the file field. That will stop form from trying to put it's value into underlying object (Product
instance).
After doing that you can handle the value on your own, which is handle file upload, create AppBundle/Entity/File
instance and put it into $product
variable via setter.
That the lazy solution, but if you would like to do the same in other forms, you will have to copy the code to every controller that needs it. So it's easier only for one time usage.
The right solution would be to convert UploadedFile
to you File
object with a Data Transformer. It's a longer topic to talk about and exact solution depends on your data flow that you want to achieve. Therefore if you want to do this right, read about Data Transformers in Symfony's docs first.
I promise that you will thank yourself later if you do that the right way. I've spent some time on understanding Symfony Form Component including Data Transformers and solved a similar issue that way. Now it pays back. I have reusable image upload form that handles even removing previously uploaded files in edit forms.
P.S. It's "entity", not "entiry". You've wrote "entiry" twice, so I'm just saying FYI.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With