Symfony 2 | 修改带有文件(图片)字段的对象时出现表单异常

18

我正在使用Symfony2。 我有一个实体Post,它有一个标题和一个图片字段。

我的问题:当我创建一个帖子时,一切都很好,我有我的图片等等。但是当我想要修改它时,我遇到了一个问题,"图片"字段是一个已上传的文件,Symfony希望是一个文件类型,但它是一个字符串(已上传文件的路径):

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. 

我遇到了这个问题,真的不知道该如何解决,非常感谢任何帮助!非常感谢!

以下是我用于 newAction() 和 modifyAction() 的 PostType.php(位于 Form/PostType.php),可能是导致问题的原因:

<?php
namespace MyBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;

use MyBundle\Entity\Post;

class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('title')
        ->add('picture', 'file');//there is a problem here when I call the modifyAction() that calls the PostType file.
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'data_class' => 'MyBundle\Entity\Post',
        );
    }

    public static function processImage(UploadedFile $uploaded_file, Post $post)
    {
        $path = 'pictures/blog/';
        //getClientOriginalName() => Returns the original file name.
        $uploaded_file_info = pathinfo($uploaded_file->getClientOriginalName());
        $file_name =
            "post_" .
            $post->getTitle() .
            "." .
            $uploaded_file_info['extension']
            ;

        $uploaded_file->move($path, $file_name);

        return $file_name;
    }

    public function getName()
    {
        return 'form_post';
    }
}

这里是我的 帖子实体 (Entity/Post.php):

<?php

namespace MyBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

use Symfony\Component\Validator\Constraints as Assert;

/**
 * MyBundle\Entity\Post
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Post
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     * @Assert\Image(
     *      mimeTypesMessage = "Not valid.",
     *      maxSize = "5M",
     *      maxSizeMessage = "Too big."
     *      )
     */
    private $picture;

    /**
     * @var string $title
     *
     * @ORM\Column(name="title", type="string", length=255)
     */
    private $title;

   //getters and setters
   }

这是我的newAction() (Controller/PostController.php) 这个函数运行正常:

public function newAction()
{
    $em = $this->getDoctrine()->getEntityManager();
    $post = new Post();
    $form = $this->createForm(new PostType, $post);
    $post->setPicture("");
    $form->setData($post);
    if ($this->getRequest()->getMethod() == 'POST') 
    {
        $form->bindRequest($this->getRequest(), $post);
        if ($form->isValid()) 
        {
            $uploaded_file = $form['picture']->getData();
            if ($uploaded_file) 
            {
                $picture = PostType::processImage($uploaded_file, $post);
                $post->setPicture('pictures/blog/' . $picture);
            }
            $em->persist($post);
            $em->flush();
            $this->get('session')->setFlash('succes', 'Post added.');

            return $this->redirect($this->generateUrl('MyBundle_post_show', array('id' => $post->getId())));
        }
    }

    return $this->render('MyBundle:Post:new.html.twig', array('form' => $form->createView()));
}

这是我的modifyAction()函数(控制器/PostController.php):这个函数存在问题

public function modifyAction($id)
{
    $em = $this->getDoctrine()->getEntityManager();
    $post = $em->getRepository('MyBundle:Post')->find($id);
    $form = $this->createForm(new PostType, $post);//THIS LINE CAUSES THE EXCEPTION
    if ($this->getRequest()->getMethod() == 'POST') 
    {
        $form->bindRequest($this->getRequest(), $post);
        if ($form->isValid()) 
        {
            $uploaded_file = $form['picture']->getData();
            if ($uploaded_file) 
            {
                $picture = PostType::processImage($uploaded_file, $post);
                $post->setPicture('pictures/blog/' . $picture);
            }
            $em->persist($post);
            $em->flush();
            $this->get('session')->setFlash('succes', 'Modifications saved.');

            return $this->redirect($this->generateUrl('MyBundle_post_show', array('id' => $post->getId())));
        }
    }
    return $this->render('MyBundle:Post:modify.html.twig', array('form' => $form->createView(), 'post' => $post));
}
3个回答

43

我通过将data_class设置为null来解决了这个问题:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
    ->add('title')
    ->add('picture', 'file', array('data_class' => null)
    );
}

你弄清楚了吗,为什么这最终解决了问题? - nbro

3
我建议您阅读Symfony和Doctrine的文件上传文档如何使用Doctrine处理文件上传,并强烈推荐部分生命周期回调
简而言之,在表单中通常使用'file'变量(请参阅文档),您可以通过选项放置不同的标签,然后在您的'picture'字段中,只需存储文件的名称,因为当您需要src文件时,只需调用getWebpath()方法即可。
->add('file', 'file', array('label' => 'Post Picture' )
);

在你的Twig模板中调用
<img src="{{ asset(entity.webPath) }}" />

1
请在您的 PostType.php 文件中进行以下更改。
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
    ->add('title')
    ->add('picture', 'file', array(
            'data_class' => 'Symfony\Component\HttpFoundation\File\File',
            'property_path' => 'picture'
        )
    );
}

嗨@Reveclaire,请告诉我这是否有帮助。如果它出现错误,您可以删除“property_path”属性。否则请保留它。 - Jirilmon
1
嗨@OMG!非常感谢您的回答。我按照您说的修改了PostType.php(包括和不包括'property_path'),但不幸的是,我仍然遇到相同的错误。 - Reveclair
我通过将 data_class 设置为 null 解决了这个问题。感谢您让我找到正确的解决方案。 - Reveclair

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接