发生验证错误时,Symfony2表单字段未更新

Tro*_*lol 6 php symfony

这是我的表单类型:

class TestFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder->add('thumbnail', 'hidden', array(
            'label' => 'Thumbnail',
            'label_attr' => array(
                'class' => 'col-xs-2 control-label'
            ),
            'required' => false,
            'error_bubbling' => true,
            'required' => false
        ));

        $builder->add('thumbnail_data', 'file', array(
            'error_bubbling' => true,
            'required' => false
        ));
    }

    public function setDefaultOptions(\Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'X\LibraryBundle\Entity\Test',
            'cascade_validation' => true,
            'error_bubbling' => true,
        ));

    }

    public function getName()
    {
        return 'test';
    }
}
Run Code Online (Sandbox Code Playgroud)

这是实体,重要的部分是setThumbnailData($ file)方法,它存储缩略图文件并通过setThumbnail(string)方法设置缩略图路径.

<?php

namespace X\LibraryBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Test
 *
 * @ORM\Table(name="test")
 * @ORM\Entity(repositoryClass="X\LibraryBundle\Repository\TestRepository")
 */
class Test
{
    /**
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="text", nullable=true)
     */
    protected $thumbnail;

    /**
     * Set thumbnail
     *
     * @param string $thumbnail
     * @return Test
     */
    public function setThumbnail($thumbnail)
    {
        $this->thumbnail = $thumbnail;

        return $this;
    }

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

    /**
     * This will save file to disk
     * @param $file
     */
    public function setThumbnailData($file) {
        if($file !== null && $file !== false)
        {
            $fileName = $file->getClientOriginalName();
            $baseDir = __DIR__ . '/../../../../../../../web/uploads/promotional_material/';
            $dir =  sha1(microtime());
            while (is_dir($baseDir . $dir)) {
                $dir = sha1(microtime());
            }
            mkdir($baseDir . $dir);
            $this->setThumbnail('/uploads/promotional_material/' . $dir . '/' . $fileName);
            $file->move($baseDir . $dir, $fileName);
        }
    }

    public function getThumbnailData() {
        return '';
    }
}
Run Code Online (Sandbox Code Playgroud)

现在的问题是,如果表单遇到验证错误,则以下树枝线产生不同的输出,从第二行输出的正确值,另一个产生原始缩略图路径.因此,如果我使用{{form_widget(form.thumbnail)}}输出缩略图输入,我将获得原始缩略图路径,而不是应通过setThumbnailData()方法更改的路径.

{{ dump(form.thumbnail.vars.data) }}
{{ dump(form.vars.data.thumbnail) }}
Run Code Online (Sandbox Code Playgroud)

使用setThumbnailData()方法设置缩略图是否会导致问题?不知道如何解决这个问题,除了硬编码输入在树枝上,如下所示:

<input type="hidden" name="test[thumbnail]" value="{{ form.vars.value.thumbnail }}"/>
Run Code Online (Sandbox Code Playgroud)

Ait*_*tch 5

我不能完全解决你的问题,因为在我看来你做错了.数据类实际上只负责保存您的数据,因此您的方法set/getThumbnailData应如下所示

<?php
// ...
private $thumbnailData;

public function setThumbnailData(UploadedFile $thumbnailData) {
    $this->thumbnailData = $thumbnailData;
}

public function getThumbnailData() {
    return $this->thumbnailData;
}
Run Code Online (Sandbox Code Playgroud)

在你的控制器中你有这样的东西:

<?php
// ...
public function formAction() {

    $form = // ... 
    $form->handleRequest($request);
    if($form->isValid()) {
        $test = $form->getData();
        /* @var $test Test */
        $thumbnailUploader = $this->get('thumbnail_uploader');
        /* @var $thumbnailUploader ThumbnailUploadService */

        $file = $test->getThumbnailData();
        $filename = $file->getClientOriginalName();
        $thumbnailUploader->upload($filename, $file);

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我建议将与表单或请求无关的所有逻辑移动到服务中.在这种情况下,您的服务可以更通用地处理具有给定文件名的任何symfony文件.

<?php
class ThumbnailUploadService {
    /**
     * @param $file Symfony\Component\HttpFoundation\File\File
     *
     */
    public function upload($filename, File $file) {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)