Symfony表单editAction与fileupload无法正常工作,因为没有文件

时间:2017-09-05 08:34:32

标签: symfony symfony-forms

我创建了一个包含2个字段的表单(名称和文件)。我已按照本指南https://symfony.com/doc/current/controller/upload_file.html

我创建了我的CRUD。我的addAction没问题。但我的编辑操作不正常。当我确认juste的表单更改名称而不是文件(输入文件中没有文件)时,表单发送错误"没有文件"。如果文件没有变化,如何在没有新文件的情况下使editAction工作?

我添加了我的项目文件

ProductController.php EditAction()

    /**
 * Displays a form to edit an existing product entity.
 *
 * @Route("/{id}/edit", name="product_edit")
 * @Method({"GET", "POST"})
 */
public function editAction(Request $request, Product $product)
{
    $deleteForm = $this->createDeleteForm($product);
    $editForm = $this->createForm('AppBundle\Form\ProductType', $product);
    $editForm->handleRequest($request);

    if ($editForm->isSubmitted() && $editForm->isValid()) {
        $this->getDoctrine()->getManager()->flush();

        return $this->redirectToRoute('product_edit', array('id' => $product->getId()));
    }

    return $this->render('product/edit.html.twig', array(
        'product'     => $product,
        'edit_form'   => $editForm->createView(),
        'delete_form' => $deleteForm->createView(),
    ));
}

ProductControlle newAction()

    /**
 * Creates a new product entity.
 *
 * @Route("/new", name="product_new")
 * @Method({"GET", "POST"})
 */
public function newAction(Request $request)
{
    $product = new Product();
    $form = $this->createForm(
        'AppBundle\Form\ProductType',
        $product,
        array(
            'validation_groups' => array('add')
        )
    );
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($product);
        $em->flush();

        return $this->redirectToRoute('product_show', array('id' => $product->getId()));
    }

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

我的产品实体

    /**
 * @var int
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;


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

/**
 * @ORM\Column(type="string")
 *
 * @Assert\NotBlank(message="Please, upload the product brochure as a PDF file.", groups={"add"})
 * @Assert\File(mimeTypes={ "application/pdf" }, groups={"add"})
 */
private $brochure;

/**
 * Get id
 *
 * @return int
 */
public function getId()
{
    return $this->id;
}

/**
 * Set name
 *
 * @param string $name
 *
 * @return Product
 */
public function setName($name)
{
    $this->name = $name;

    return $this;
}

/**
 * Get name
 *
 * @return string
 */
public function getName()
{
    return $this->name;
}

/**
 * Set brochure
 *
 * @param string $brochure
 *
 * @return Product
 */
public function setBrochure($brochure)
{
    $this->brochure = $brochure;

    return $this;
}

/**
 * Get brochure
 *
 * @return string
 */
public function getBrochure()
{
    return $this->brochure;
}

我的FileUploder(服务)

private $targetDir;

public function __construct($targetDir)
{
    $this->targetDir = $targetDir;
}

public function upload(UploadedFile $file)
{
    $fileName = md5(uniqid()) . '.' . $file->guessExtension();

    $file->move($this->getTargetDir(), $fileName);

    return $fileName;
}

public function getTargetDir()
{
    return $this->targetDir;
}

我的BrochureUploadListener.php

    private $uploader;
private $fileName;

public function __construct(FileUploader $uploader)
{
    $this->uploader = $uploader;
}

public function prePersist(LifecycleEventArgs $args)
{
    $entity = $args->getEntity();

    $this->uploadFile($entity);
}

public function preUpdate(PreUpdateEventArgs $args)
{
    $entity = $args->getEntity();

    $this->uploadFile($entity);
}

public function postLoad(LifecycleEventArgs $args)
{
    $entity = $args->getEntity();

    if (!$entity instanceof Product) {
        return;
    }

    if ($fileName = $entity->getBrochure()) {
        $entity->setBrochure(new File($this->uploader->getTargetDir().'/'.$fileName));
    }
}

private function uploadFile($entity)
{
    // upload only works for Product entities
    if (!$entity instanceof Product) {
        return;
    }

    $file = $entity->getBrochure();

    // only upload new files
    if ($file instanceof UploadedFile) {
        $fileName = $this->uploader->upload($file);
        $entity->setBrochure($fileName);
    }
}

我的services.yml

    AppBundle\Service\FileUploader:
    arguments:
        $targetDir: '%brochures_directory%'

AppBundle\EventListener\BrochureUploadListener:
    tags:
        - { name: doctrine.event_listener, event: prePersist }
        - { name: doctrine.event_listener, event: preUpdate }
        - { name: doctrine.event_listener, event: postLoad }

2 个答案:

答案 0 :(得分:0)

问题是当你使用

$form->isValid()

它实际上验证了

@Assert\NotBlank(message="Please, upload the product brochure as a PDF file.")
@Assert\File(mimeTypes={ "application/pdf" })

但您提供的是字符串而不是UploadedFile的实例。您可以做的是创建验证组以确保此断言仅在您创建新实体时起作用:

@Assert\NotBlank(message="Please, upload the product brochure as a PDF file.", groups={"add"})
@Assert\File(mimeTypes={ "application/pdf" }, groups={"add"})

然后在addAction中添加到您的表单选项中:

'validation_groups' => array('add')

因此,你在addAction中的表单实例化应该如下所示:

$form = $this->createForm(YourFormType::class, null, array(
    'validation_groups' => array('add')
));

答案 1 :(得分:0)

我使用了vichuploader捆绑包,它更简单,更好。