2015-02-10 6 views
6

Вот мой тип формы:Symfony2 поле формы не обновляется, когда ошибка проверки происходит

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'; 
    } 
} 

Вот сущность, важной частью является метод setThumbnailData ($ файл), в котором хранится файл эскиза и устанавливает миниатюру путь через метод 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 ''; 
    } 
} 

Теперь проблема, если форма работает в ошибки проверки, следующие строки прута производят различную продукцию, правильное значение, выводимое из второй линии, а другой производит исходный путь эскиза. Поэтому, если я вывожу эскиз с помощью {{form_widget (form.thumbnail)}}, я получаю исходный путь эскизов, а не тот, который должен был быть изменен с помощью метода setThumbnailData().

{{ dump(form.thumbnail.vars.data) }} 
{{ dump(form.vars.data.thumbnail) }} 

Проблема связана с настройкой миниатюры с помощью метода setThumbnailData()? Не знаю, как это исправить, кроме жесткого кодирования входа в веточке так:

<input type="hidden" name="test[thumbnail]" value="{{ form.vars.value.thumbnail }}"/> 

ответ

5

Я не могу точно решить вашу проблему, потому что на моем взгляде, вы делаете это неправильно. Класс данных на самом деле только ответственно для хранения ваших данных, так что ваш метод set/getThumbnailData должен выглядеть следующим образом

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

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

public function getThumbnailData() { 
    return $this->thumbnailData; 
} 

В контроллере у вас есть что-то вроде этого:

<?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); 

     // ... 
    } 
} 

Я рекомендую, чтобы переместить всю логику, не имеет ничего общего с формами или запросами в сервисах. Ваша служба в этом случае может быть более общей для любых файлов symfony с заданным именем файла.

<?php 
class ThumbnailUploadService { 
    /** 
    * @param $file Symfony\Component\HttpFoundation\File\File 
    * 
    */ 
    public function upload($filename, File $file) { 
     // ... 
    } 
} 
+0

Ну, я хочу сохранить файл на диск, даже если он не прошел проверку, поэтому пользователю не нужно повторно загружать изображение, если возникла ошибка проверки. – Trololololol

+0

Затем создайте новый 'Type' и' Validator', чтобы он был бесшовным для рамки формы symfony, возможно, с полем 'file' и' hidden' в качестве дочерних типов. Если вы просто сохраните файл на диск, что делать, если пользователь никогда не вводит правильные данные? – Aitch

0

Также есть другой способ использования обратных вызовов. Здесь я даю вам общий класс для загрузки изображения и создания эскизов. Надеюсь, эта работа для вас. Этот класс управляет файлами, создаваемыми автоматически при создании обновления o удалять сущность.

use Doctrine\ORM\Mapping as ORM; 
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert; 
use Symfony\Component\HttpFoundation\File\UploadedFile; 
use Symfony\Component\Validator\Constraints as Assert; 
use App\MyBundleBundle\Util\Util; 

/** 
* Image 
* 
* @ORM\Table(name="image") 
* @ORM\Entity() 
* @ORM\HasLifecycleCallbacks 
*/ 
class Image 
{ 

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

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


    private $temp; 

    /** 
    * @ORM\Column(type="string", length=255) 
    */ 
    protected $path; 

    /** 
    * @Assert\Image(maxSize="5M") 
    */ 
    private $file; 

    /** 
    * Sets file. 
    * 
    * @param UploadedFile $file 
    */ 
    public function setFile(UploadedFile $file = null) 
    { 
     $this->file= $file; 

     if (isset($this->path)) { 
      $this->temp = $this->path; 
      $this->path= null; 
     } else { 
      $this->path= 'initial'; 
     } 
    } 

    /** 
    * Get file. 
    * 
    * @return UploadedFile 
    */ 
    public function getFile() 
    { 
     return $this->file; 
    } 

    /** 
    * @ORM\PrePersist() 
    * @ORM\PreUpdate() 
    */ 
    public function preUpload() 
    { 
     if (null !== $this->getFile()) { 
      // do whatever you want to generate a unique name 
      $filename = Util::getSlug($this->name) . uniqid() . '.' . $this->file->guessExtension(); 
      $this->path = $filename; 
     } 
    } 

    /** 
    * @ORM\PostPersist() 
    * @ORM\PostUpdate() 
    */ 
    public function upload() 
    { 
     if (null === $this->getFile()) { 
      return; 
     } 

     $this->getFile()->move($this->getUploadRootDir(), $this->path); 
     if (isset($this->temp)) { 
      if (file_exists($this->getUploadRootDir() .'/'. $this->temp)) { 
       unlink($this->getUploadRootDir() . '/' . $this->temp); 
      } 
      $this->temp = null; 
     } 
     $this->file= null; 
     //create a dir to save de thumbnails 
     if (!file_exists($this->getUploadRootDir() . '/thumbnails')) { 
      mkdir($this->getUploadRootDir() . '/thumbnails'); 
     } 

     //call a method in util class to generate the thumbnails 
     Util::redim($this->getUploadRootDir() . '/' . $this->path, $this->getUploadRootDir() . '/thumbnails/' . $this->path, 128, 128); 
    } 

    /** 
    * @ORM\PostRemove() 
    */ 
    public function removeUpload() 
    { 
     //This is to remove the files when the entity is delete 
     if ($file = $this->getAbsolutePath()) { 
      if (file_exists($file)) { 
       unlink($file); 
       $thumb = $this->getUploadRootDir() . '/thumbnails/' . $this->getPath(); 
       if (file_exists($thumb)) { 
        unlink($thumb); 
       } 
      } 
     } 
    } 

    public function getAbsolutePath() 
    { 
     return null === $this->path ? null : $this->getUploadRootDir() . '/' . $this->path; 
    } 

    public function getWebPath() 
    { 
     return null === $this->path? null : 
      $this->getUploadDir() . '/' . $this->path; 
    } 

    protected function getUploadRootDir() 
    { 
     return $this->getUploadDir(); 
    } 

    protected function getUploadDir() 
    { 
     return 'uploads/image/'; 
    } 

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

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

     return $this; 
    } 

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


    /** 
    * Set path 
    * 
    * @param string $path 
    * @return Imagen 
    */ 
    public function setPath($path) 
    { 
     $this->path= $path; 

     return $this; 
    } 

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

    public function __toString() 
    { 
     return $this->getName(); 
    } 
}