Symfony 3 文件上传

Symfony 3 FileUpload

我正在尝试使用 Symfony 3 为我的应用程序实现文件上传功能。 我有一个产品条目,与文件条目有关。 部分产品:

 /**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\File", mappedBy="product")
 * @ORM\OrderBy({"weight" = "DESC"})
 */
protected $files;

表单上的字段:

     ->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',
    ));
}

如您所见,我已设置 data_class。

在控制器中我正在尝试处理表单

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); 
    ...

我有一个错误:

Expected argument of type "AppBundle\Entity\File", "Symfony\Component\HttpFoundation\File\UploadedFile" given

如果我删除 data_class 映射,我没有错误也没有对象,只有数组。 如何解决此错误,如何将 UploadedFile 转换为 File (Entiry)。我正在尝试创建 Transformer,但我刚得到 ProductEntiry class,结果无法处理它,因为它没有文件。

在进入正题之前,先提一个建议。排队:

$form = $this->createForm(ProductType::class, null);

我会提供 $product 变量,这样它会自动填充数据而不是创建新数据。所以应该改成:

$form = $this->createForm(ProductType::class, $product);

好的,现在,问题出现了,因为你的 Product class 中可能有一个 setter 像:

public function addFile(AppBundle\Entity\File $file) { ... }

然后,在成功验证之后,表单会尝试用来自表单的数据填充 Product class 的实例,其中包含 Symfony 的 UploadedFile class 实例。我希望你明白这一点。

现在,您(至少)有两种可能的解决方案。

您可以为文件字段设置"mapped" => false选项。这将阻止表单尝试将其值放入基础对象(Product 实例)。

完成后你可以自己处理这个值,即处理文件上传,创建AppBundle/Entity/File实例并通过setter.[=24将它放入$product变量中=]

惰性解决方案,但如果您想以其他形式执行相同的操作,则必须将代码复制到需要它的每个控制器。所以仅一次性使用.

更容易

正确的解决方案是首先在 Symfony 的文档中使用 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 TransformersUploadedFile 转换为您的 File 对象。

我保证,如果您以正确的方式做到这一点,您稍后会感谢自己。我花了一些时间来理解包括数据转换器在内的 Symfony 表单组件,并以这种方式解决了类似的问题。现在它得到了回报。我有可重复使用的图像上传表单,它甚至可以处理删除以前在编辑表单中上传的文件。

P.S。 是 "entity",不是 "entiry"。您已经写了两次 "entiry",所以我只是说一下。