Symfony2 form field does not update when validation error occurs

Here is my form type:

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

Here is the essence, the important part is the setThumbnailData ($ file) method, which stores the thumbnail file and sets the thumbnail path using the setThumbnail (string) method.

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

Now the problem is that if the form starts in a validation error, the following lines of the line produce different output, the correct value displayed from the second line, the other creates the original sketch path. Therefore, if I display a sketch using {{form_widget (form.thumbnail)}}, I get the original sketch path, and not the one that should have been modified using the setThumbnailData () method.

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

Is the problem related to setting the sketch using the setThumbnailData () method? You do not know how to fix this, except for hard-coding input in a branch, for example:

 <input type="hidden" name="test[thumbnail]" value="{{ form.vars.value.thumbnail }}"/> 
+6
source share
2 answers

I can’t solve your problem exactly because, in my opinion, you are doing it wrong. The data class is actually only responsible for storing your data, so your set/getThumbnailData should look like this:

 <?php // ... private $thumbnailData; public function setThumbnailData(UploadedFile $thumbnailData) { $this->thumbnailData = $thumbnailData; } public function getThumbnailData() { return $this->thumbnailData; } 

In your controller, you have something like this:

 <?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); // ... } } 

I recommend moving all logic that has nothing to do with forms or service requests. Your service in this case may be more general for any symfony files with a given file name.

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

There is also another way to use callbacks . Here I give you a general class for uploading images and creating thumbnails. Hope this work is for you. This class manages files that are created automatically when an update is created. O deletes the object.

 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(); } } 
0
source

Source: https://habr.com/ru/post/982289/


All Articles