EasyAdminBundle: Cannot modify entity with required file field from VichUploaderBundle

Hello,

I have Page entity class which has, among others, these properties:

class Page
{
    // ...

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

    /**
     * @Vich\UploadableField(mapping="product_images", fileNameProperty="image")
     * @var File
     * @Assert\File()
     * @Assert\NotBlank()
     */
    private $imageFile;

    // ...
}

Everything is all right when I’m creating new entity trough EasyAdmin panel. The problem starts when I want to edit something from this particular entity without changing the $image property. When I’m clicking submit button, error occurs:

untitled-1

How to make $image file property as “required” while allowing it to edit entity when the file is uploaded earlier?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 17 (7 by maintainers)

Most upvoted comments

@javiereguiluz

Thanks to @laurent-bientz and its solution for image validation, I propose that we close this issue (and remove the bug and unconfirmed labels).

Here is a summary for image validation when the image is mandatory (non-nullable).

Considering the following entity (getters and setters are not given):

namespace Namespace\Entity

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;


/**
 * @Vich\Uploadable
 */
class MyEntity
{
    /**
     * @var File
     *
     * @Vich\UploadableField(mapping="images", fileNameProperty="image")
     */
    private $file;

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

Config file + front validation :

MyEntity:
  class : Namespace\Entity\MyEntity
  form:
      #....
  new:
      fields:
         # No image at entity creation so it is required.
         # Image deletion at form level has to be disabled.
          - { property: 'file', type: 'vich_image', type_options: { required: true, allow_delete: false} }
  edit:
      fields:
          # An image has already been uploaded, image is not required.
          # Image deletion at form level has to be disabled.
          - { property: 'file', type: 'vich_image', type_options: { required: false, allow_delete: false} }

Back validation:

namespace Namespace\Entity

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


/**
 * @Vich\Uploadable
 */
class MyEntity
{
    /**
     * @var File
     *
     * @Vich\UploadableField(mapping="images", fileNameProperty="image")
     * @Assert\Expression("this.getFile() or this.getImage()", message="admin.validation.image.upload")
     */
    private $file;

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

First, a quick comment: you should enable the translator service in Symfony. See that buttons and links display weird strings like action.save instead of Save. Just uncomment this line in app/config/config.yml:

framework:
    #esi:             ~
    translator:      { fallbacks: [%locale%] }  # <-- UNCOMMENT THIS LINE
    # ...

The situation appears when a persistant non-nullable field (eg “photo”) is binded on a virtual field for the file (eg photoFile) with an Assert\NotBlank().

When we try to edit the recordset (no problem when adding), the assert on the file forces user to reupload the file, even if the field photo is set (in front with HTML validation and in back with assert on file), so the validation fails.

Putting a validation group on each entity with a non-nullable file is a pain.

Don’t know if it’s the best way but I solve the problem with an expression assert which checks both fields instead of only the virtual field:

/**
 * @var File
 *
 * @Vich\UploadableField(mapping="about_image", fileNameProperty="photo")
 * @Assert\Expression("this.getPhotoFile() or this.getPhoto()", message="Vous devez uploader une photo.")
 * @Assert\Image(
 *     minWidth="1600",
 *     minWidthMessage="Votre photo doit faire minimum 1600px de largeur.",
 *     minHeight="500",
 *     minHeightMessage="Votre photo doit faire minimum 500px de hauteur.",
 *     mimeTypes={"image/jpeg", "image/png", "image/gif"},
 *     mimeTypesMessage="Formats autorisés : .png, .jpeg, .jpg, gif "
 *     )
 */
private $photoFile;

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

and don’t forget to disable the allow_delete on the field, cause nonsense to allow delete on a non-nullable field:

- { property: 'photoFile', label: 'Photo', type: 'vich_image', help: 'Taille recommandée: 1920*620 px', type_options: { allow_delete: false } }

Hope it helps, if someone have a best idea, I’ll take it 😉