Symfony2:如果未提供,请不要更新表单字段

VaN*_*VaN 10 persistence symfony doctrine-orm

我有一个表单给我的"团队"实体.该实体具有"图像"字段.此字段在创建过程中是必需的,但在编辑过程中不需要.但是现在,在编辑过程中,如果我没有在文件输入中提供任何图像,则空输入仍然存在,因此我的数据库字段在此过程中被清空.如果表单文件输入中没有提供任何内容,我该怎么做才能避免此字段的持久性?因此,实体保留此字段的旧值.当然,如果提供了一个文件,我希望他删除旧文件.

我的控制器看起来像这样:

if ($request->getMethod() == 'POST') {

    $form->bind($request);

    if ($form->isValid()) {

        $em->persist($team);
        $em->flush();
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

和我的实体的一部分,处理图像(我很确定我必须在这里做一些事情,但不知道到底是什么):

/**
 * @ORM\PrePersist()
 * @ORM\PreUpdate()
 */
public function uploadImage() {
    // the file property can be empty if the field is not required
    if (null === $this->image) {
        return;
    }
    if(!$this->id){
        $this->image->move($this->getTmpUploadRootDir(), $this->image->getClientOriginalName());
    }else{
        $this->image->move($this->getUploadRootDir(), $this->image->getClientOriginalName());
    }
    $this->setImage($this->image->getClientOriginalName());
}
Run Code Online (Sandbox Code Playgroud)

编辑

好吧,我对这个答案的代码进行了一些更改,因为显然事件监听器FormEvent在他的回调中要求一个实例,而不是一个FormInterface实例.

$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
// Retrieve submitted data
$form = $event->getForm();
$item = $event->getData();

// Test if upload image is null (maybe adapt it to work with your code)
if (null !== $form->get('image')->getData()) {
    var_dump($form->get('image')->getData());
    die('image provided');
    $item->setImage($form->get('image')->getData());
}
Run Code Online (Sandbox Code Playgroud)

});

当我提供图像时,脚本会进入测试,并且die()正如预期的那样.当我不提供任何文件时,脚本不会进入测试if(),但数据库中的我的字段仍然使用空值擦除.任何的想法?

如下所述,这是表格

// src/Van/TeamsBundle/Form/TeamEditType.php

namespace Van\TeamsBundle\Form;

use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

class TeamEditType extends TeamType // Ici, on hérite de ArticleType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // On fait appel à la méthode buildForm du parent, qui va ajouter tous les champs à $builder
        parent::buildForm($builder, $options);
        // On supprime celui qu'on ne veut pas dans le formulaire de modification
        $builder->remove('image')
        ->add('image', 'file', array(
            'data_class' => null,
            'required' => false
        ))
        ;


        $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
            // Retrieve submitted data
            $form = $event->getForm();
            $item = $event->getData();

            // Test if upload image is null (maybe adapt it to work with your code)
            if (null !== $form->get('image')->getData()) {
                var_dump($form->get('image')->getData());
                die('image provided');
                $item->setImage($form->get('image')->getData());
            }
        });


    }

    // On modifie cette méthode car les deux formulaires doivent avoir un nom différent
    public function getName()
    {
        return 'van_teamsbundle_teamedittype';
    }
}
Run Code Online (Sandbox Code Playgroud)

以及整个团队实体:

<?php

namespace Van\TeamsBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Team
 *
 * @ORM\Table()
 * @ORM\HasLifecycleCallbacks
 * @ORM\Entity
 * @ORM\Entity(repositoryClass="Van\TeamsBundle\Entity\TeamRepository") @ORM\Table(name="van_teams")
 */
class Team
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

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

    /**
     * @ORM\ManyToOne(targetEntity="Van\TeamsBundle\Entity\Game")
     * @ORM\JoinColumn(nullable=false)
     */
    private $game;

    /**
     * @ORM\ManyToOne(targetEntity="Van\TeamsBundle\Entity\Statut")
     * @ORM\JoinColumn(nullable=false)
     */
    private $statut;

    /**
     * @var string $image
     * @Assert\File( maxSize = "1024k", mimeTypesMessage = "Please upload a valid Image")
     * @ORM\Column(name="image", type="string", length=255)
     */
    private $image;



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

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

        return $this;
    }

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

    /**
     * Set countryCode
     *
     * @param string $countryCode
     * @return Team
     */
    public function setCountryCode($countryCode)
    {
        $this->countryCode = $countryCode;

        return $this;
    }

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

    /**
     * Set image
     *
     * @param string $image
     * @return Team
     */
    public function setImage($image)
    {
        $this->image = $image;

        return $this;
    }

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

    /**
     * Set game
     *
     * @param \Van\TeamsBundle\Entity\Game $game
     * @return Team
     */
    public function setGame(\Van\TeamsBundle\Entity\Game $game)
    {
        $this->game = $game;

        return $this;
    }

    /**
     * Get game
     *
     * @return \Van\TeamsBundle\Entity\Game 
     */
    public function getGame()
    {
        return $this->game;
    }

    /**
     * Set statut
     *
     * @param \Van\TeamsBundle\Entity\Statut $statut
     * @return Team
     */
    public function setStatut(\Van\TeamsBundle\Entity\Statut $statut)
    {
        $this->statut = $statut;

        return $this;
    }

    /**
     * Get statut
     *
     * @return \Van\TeamsBundle\Entity\Statut 
     */
    public function getStatut()
    {
        return $this->statut;
    }






    public function getFullImagePath() {
        return null === $this->image ? null : $this->getUploadRootDir(). $this->image;
    }

    protected function getUploadRootDir() {
        // the absolute directory path where uploaded documents should be saved
        // return $this->getTmpUploadRootDir();
        return __DIR__ . '/../../../../web/uploads/';
    }

    protected function getTmpUploadRootDir() {
        // the absolute directory path where uploaded documents should be saved
        return __DIR__ . '/../../../../web/uploads_tmp/';
    }

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function uploadImage() {
        // the file property can be empty if the field is not required
        if (null === $this->image) {
            return;
        }
        if(!$this->id){
            $this->image->move($this->getTmpUploadRootDir(), $this->image->getClientOriginalName());
        }else{
            $this->image->move($this->getUploadRootDir(), $this->image->getClientOriginalName());
        }
        $this->setImage($this->image->getClientOriginalName());
    }

    /**
     * @ORM\PostPersist()
     */
    public function moveImage()
    {
        if (null === $this->image) {
            return;
        }
        if(!is_dir($this->getUploadRootDir())){
            mkdir($this->getUploadRootDir());
        }
        copy($this->getTmpUploadRootDir().$this->image, $this->getFullImagePath());
        unlink($this->getTmpUploadRootDir().$this->image);
    }

    /**
     * @ORM\PreRemove()
     */
    public function removeImage()
    {
        unlink($this->getFullImagePath());
        rmdir($this->getUploadRootDir());
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑2

我做到了 当我提供图像时,它将保存在数据库的图像字段中,并重定向到我的索引页面.当我不提供任何图像时,不会发生重定向,并且在我的文件输入中出现以下消息:"无法找到该文件." 在我的TeamEditType班上,我做了以下,所以不应该要求图像.

$builder->remove('image')
->add('image', 'file', array(
    'data_class' => null,
    'required' => false
))
;
Run Code Online (Sandbox Code Playgroud)

Rou*_*ubi 15

从Symfony 2.3开始,您可以简单地使用PATCH http方法,如此处所述.

    $form = $this->createForm(FooType::class, $foo, array(
        'action' => $this->generateUrl('foo_update', array('id' => $foo->getId())),
        'method' => 'PATCH',
    ));
Run Code Online (Sandbox Code Playgroud)

这是使用主窗体部分更新实体的简单方法,无需渲染所有字段.


Deb*_*lav 6

Symfony 2.4中的一种方法(Symfony2 coockbook中的更多信息):

public function buildForm(FormBuilderInterface $builder, array $options)
{
 // $builder->add() ... 

 $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormInterface $form) {
        // Retrieve submitted data
        $form = $event->getForm();
        $image = $form->getData();

        // Test if upload image is null (maybe adapt it to work with your code)
        if (null !== $form->get('uploadImage')->getData()) {
            $image->setUploadImage($form->get('uploadImage')->getData());
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

编辑

您似乎已经在测试了prepersit数据.请尝试以下方法:

   public function setImage($image)
   {
        if($image !== null) {
            $this->image = $image;

            return $this;
        } 
    }
Run Code Online (Sandbox Code Playgroud)