首页 文章

Symfony 3 FileUpload

提问于
浏览
4

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

/**
 * @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); 
    ...

我有一个错误:

给出“AppBundle \ Entity \ File”类型的预期参数,给出“Symfony \ Component \ HttpFoundation \ File \ UploadedFile”

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

1 回答

  • 7

    在我谈到这一点之前,只有一个建议 . 排队:

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

    我会提供 $product 变量,因此它将自动填充数据而不是创建新数据 . 所以应该改为:

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

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

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

    然后,在成功验证之后,表单尝试使用表单中的数据填充 Product 类的实例,该表单包含Symfony的 UploadedFile 类实例 . 我希望你明白这一点 .

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

    您可以为文件字段设置 "mapped" => false 选项 . 这将阻止形式尝试将其值放入底层对象( Product 实例) .

    执行此操作后,您可以自己处理该值,即处理文件上传,创建 AppBundle/Entity/File 实例并通过setter将其放入 $product 变量中 .

    这是一个懒惰的解决方案,但如果你想以其他形式做同样的事情,你将不得不将代码复制到需要它的每个控制器 . 因此,仅一次性使用更容易 .

    正确的解决方案是使用Data TransformerUploadedFile 转换为 File 对象 . 这是一个较长的话题,确切的解决方案取决于您想要实现的数据流 . 因此,如果您想要正确执行此操作,请首先阅读Symfony文档中的Data Transformers .

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

    附:它是"entity",而不是"entiry" . 你已经两次写了"entiry",所以我只是说FYI .

相关问题