Make file not nullable in VichUploaderBundle

1k views Asked by At

I'm using VichUploaderBundle in my Symfony2.8 application to add file attribute to my entity. Please see code of entity below.

namespace WebsiteBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\HttpFoundation\File\File as UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
 * @ORM\Table(name="website_file")
 * @ORM\Entity(repositoryClass="WebsiteBundle\Repository\FileRepository")
 * @Vich\Uploadable
 */
class File
{
    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     * @Assert\Type(type="integer")
     * @Assert\GreaterThan(value="0")
     */
    private $id;

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

    /**
     * @var string
     *
     * @ORM\Column(type="text")
     * @Assert\NotBlank()
     * @Assert\Type(type="string")
     */
    private $description;

    /**
     * @var UploadedFile
     *
     * @Vich\UploadableField(mapping="file", fileNameProperty="filename")
     */
    private $file;

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

    /**
     * @var int
     *
     * @ORM\Column(type="integer")
     * @Assert\NotNull()
     * @Assert\Type(type="integer")
     * @Assert\GreaterThanOrEqual(value="0")
     */
    private $dummy = 0;

    /**
     * @var boolean
     *
     * @ORM\Column(type="boolean")
     * @Assert\NotNull()
     * @Assert\Type(type="boolean")
     */
    private $published;

    /**
     * @var User
     *
     * @Gedmo\Blameable(on="create")
     * @ORM\ManyToOne(targetEntity="WebsiteBundle\Entity\User")
     * @ORM\JoinColumn(onDelete="CASCADE")
     * @Assert\Type(type="WebsiteBundle\Entity\User")
     * @Assert\Valid()
     */
    private $createdBy;

    /**
     * @var \DateTime
     *
     * @Gedmo\Timestampable(on="create")
     * @ORM\Column(type="datetime")
     * @Assert\DateTime()
     */
    private $createdAt;

    /**
     * @var User
     *
     * @Gedmo\Blameable(on="update")
     * @ORM\ManyToOne(targetEntity="WebsiteBundle\Entity\User")
     * @ORM\JoinColumn(onDelete="CASCADE")
     * @Assert\Type(type="WebsiteBundle\Entity\User")
     * @Assert\Valid()
     */
    private $updatedBy;

    /**
     * @var \DateTime
     *
     * @Gedmo\Timestampable(on="update")
     * @ORM\Column(type="datetime")
     * @Assert\DateTime()
     */
    private $updatedAt;

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

    /**
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * @param string $title
     */
    public function setTitle($title)
    {
        $this->title = $title;
    }

    /**
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * @param string $description
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

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

    /**
     * @param UploadedFile $file
     */
    public function setFile($file)
    {
        $this->file = $file;
        $this->dummy++;
    }

    /**
     * @return string
     */
    public function getFilename()
    {
        return $this->filename;
    }

    /**
     * @param string $filename
     */
    public function setFilename($filename)
    {
        $this->filename = $filename;
    }

    /**
     * @return boolean
     */
    public function getPublished()
    {
        return $this->published;
    }

    /**
     * @param boolean $published
     */
    public function setPublished($published)
    {
        $this->published = $published;
    }

    /**
     * @return User
     */
    public function getCreatedBy()
    {
        return $this->createdBy;
    }

    /**
     * @param User $createdBy
     */
    public function setCreatedBy($createdBy)
    {
        $this->createdBy = $createdBy;
    }

    /**
     * @return \DateTime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * @param \DateTime $createdAt
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;
    }

    /**
     * @return User
     */
    public function getUpdatedBy()
    {
        return $this->updatedBy;
    }

    /**
     * @param User $updatedBy
     */
    public function setUpdatedBy($updatedBy)
    {
        $this->updatedBy = $updatedBy;
    }

    /**
     * @return \DateTime
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }

    /**
     * @param \DateTime $updatedAt
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;
    }
}

And everything works fine with one exception. I want to make filename not nullable. File has to be uploaded on creating entity and cannot be deleted during update. It can be only changed. Some file always has to be uploaded to entity. How to achieve this? If I add assert for filename like:

* @Assert\NotNull()

Then it not working, because during validating form, filename is empty. It is generated during persisting entity. But if I omit this assert, then it is possible to persist entity without uploading file.

1

There are 1 answers

0
dawounit On BEST ANSWER

The solution was so simple and so close. I just need to add custom validator to my File entity. How I done this?

Firstly I added annotation to File entity. Please see code below

/**
 * @ORM\Table(name="website_file")
 * @ORM\Entity(repositoryClass="WebsiteBundle\Repository\FileRepository")
 * @Vich\Uploadable
 * @Assert\Callback({"WebsiteBundle\Validator\Entities\FileValidator", "validate"})
 */
class File

Annotations for properties remain the same.

/**
 * @var UploadedFile
 *
 * @Vich\UploadableField(mapping="file", fileNameProperty="filename")
 * @Assert\Type(type="Symfony\Component\HttpFoundation\File\UploadedFile")
 */
private $file;

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

And the last step - Validator which is really simple.

class FileValidator
{
    /**
     * @param File $file
     * @param ExecutionContextInterface $context
     */
    public static function validate(File $file, ExecutionContextInterface $context)
    {
        if ($file->getFilename() === null && $file->getFile() === null) {
            $context->buildViolation('File cannot be empty.')
                ->atPath('file')
                ->addViolation();
        }
    }
}

Add thanks to this the file has to be uploaded for entity and it cannot be removed during update.