2016-08-18 88 views
4

我正在尝试使用Symfony 3为我的应用程序实现文件上传功能。 我有一个产品entiry,它与File entiry有关系。产品 部分: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转换为文件(完全)。我试图创建Transformer,但我刚刚获得了ProductEntiry类,并且因为结果无法处理它,因为它没有文件。

回答

7

在开始谈论之前,只有一点建议。在行:

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

我将提供$product变量,它会自动填充数据,而不是创造新的。因此,它应改为:

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

好了,现在,出现了问题,因为你可能在你的Product类像二传手:

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

然后,验证成功后,形式尝试填入Product类的实例与表格中的数据,其中包含Symfony的UploadedFile类实例。我希望你明白这一点。

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

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

这样做后,你可以自己处理值,这是处理文件上传,创建AppBundle/Entity/File实例,并通过setter把它变成$product变量。

懒惰解决方案,但如果你想在其他形式做相同的,你将不得不将代码复制到每个需要它的控制器。所以只有一次性使用更容易。

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

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

P.S. 这是“实体”,而不是“entiry”。你已经写了“entiry”两次,所以我只是说FYI。

+0

感谢您的回答。其作品 –