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:

How to make $image file property as "required" while allowing it to edit entity when the file is uploaded earlier?
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
# ...
If I understand your problem well, you want to make a field sometimes mandatory and sometimes optional. That's called "Validation Groups" in Symfony. They are explained here: http://symfony.com/doc/current/book/forms.html#validation-groups
If that's right, you need to define the validation groups in your application and then tell EasyAdmin which validation groups to use on each view. Here you can see an example: https://github.com/javiereguiluz/EasyAdminBundle/blob/master/Resources/doc/book/4-edit-new-configuration.md#defining-custom-form-options That example uses the special form view, but you need to define both the new and edit views to define different validation groups.
I'm closing this because it looks related to Symfony validation and not the bundle itself. If I'm wrong, please reopen it. Thanks!
@javiereguiluz
I still got the problem.
Entity class:
<?php
namespace Notimeo\PageBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
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;
use Notimeo\UserBundle\Entity\User;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* Page
*
* @ORM\Table(name="pages")
* @ORM\Entity(repositoryClass="Notimeo\PageBundle\Repository\PageRepository")
* @Gedmo\TranslationEntity(class="Notimeo\PageBundle\Entity\Page\PageTranslation")
* @ORM\HasLifecycleCallbacks
* @Vich\Uploadable
*/
class Page
{
// ...
/**
* @Vich\UploadableField(mapping="product_images", fileNameProperty="image")
* @Assert\NotBlank(groups={"add_page"})
* @var File
*/
private $imageFile;
// ...
}
EasyAdmin config:
easy_admin:
Page:
class: Notimeo\PageBundle\Entity\Page
list:
fields:
- title
- { property: 'image', type: 'image', base_path: "%app.path.product_images%" }
- updateDate
show:
fields:
- { property: 'image', type: 'image', base_path: "%app.path.product_images%" }
new:
form_options: { validation_groups: ['Default', 'add_page'] }
edit:
form_options: { validation_groups: ['not_existing_group'] }
form:
form_options: { validation_groups: ['not_existing_group'] }
fields:
- isPublished
- property: 'title'
type: 'Notimeo\PageBundle\Form\TranslatableType'
type_options:
personal_translation: 'Notimeo\PageBundle\Entity\Page\PageTranslation'
property_path: 'translations'
- { property: 'content', type: 'Notimeo\PageBundle\Form\TranslatableType', type_options: { widget: 'Ivory\CKEditorBundle\Form\Type\CKEditorType', personal_translation: 'Notimeo\PageBundle\Entity\Page\PageTranslation', 'property_path': 'translations' } }
- property: 'imageFile'
type: 'vich_image'
type_options:
allow_delete: false
- { property: 'pageFiles', type: 'collection', type_options: { entry_type: 'Notimeo\PageBundle\Form\Type\MyFileType', by_reference: false } }
And imageFile field in form is still "required" in "edit" form page. What I'm doing wrong?
@javiereguiluz
I think I can't reopen this issue :D.
https://github.com/ktrzos/SymfonyBasic
My app with this problem (in NotimeoPageBundle)...
The @Assert\NotBlank(groups={"add_page"}) is setting required = true for particular form field. So, I think, that this flag is set every time independently from validation groups...
Does the database allow this field to be null? The imageFile property should add nullable=true to its @ORM annotation.
@javiereguiluz
I susbcribed to this post a long time ago, and since, I had to face the same issue. So if it can help here is my solution (used also for plainPassword field with FOSUserBundle integration)
If I understand, the problem is only on client side. So, depending on the view (new or edit), the imageFile property should be required or not. Actually, this can be solved by fully defining new and edit view and modifying required type option for imageFile property. But thanks to PR #1341 that should be merged soon (thank you Javier), this could be done:
form:
#....
new:
fields:
- { property: 'imageFile', type: 'vich_image', type_options: { required: true} }
edit:
fields:
- { property: 'imageFile', type: 'vich_image', type_options: { required: false} }
I think there is no bug.
PS : imageFile property is not a mapped field, so using @ORM\JoinColumn(nullable=true) won't have any impact on database side ?
The situation appears when a persistant non-nullable field (eg "photo") is binded on a virtual field for the file (eg photoFile) with an AssertNotBlank().
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 ;)
@laurent-bientz
Did you try to disable the HTML validation for edition (type_options: { required: false})? In this case and using a classical assertion on photoFile property (without Expression), does the validation still fail ?
In my case it works : I can edit my main entity without having to re-upload an image (I have a dedicated Image entity with a OneToOne relationship with my main entity).
and don't forget to disable the allow_delete on the field, cause nonsense to allow delete on a non-nullable field:
I agree, I did the same thing.
@CruzyCruz, yes I did, no problem in Front but error (caused by NotBlank() assert) after submiting.
No OneToOne relation for me, it's directly a field in the current entity, maybe it's the difference.
@laurent-bientz
You are right. I forgot a little something. In my case, with a OneToOne relationship, I have to add at relationship level (i.e on the image property of my main entity) anAssert\NotNull() in addition to @Assert\Valid(). So even without HTML validation, it won't be possible to record the data without having correctly filled the Image embedded form (and I don't need Assert\NotBlank() on file property). But it's not an elegant solution. Moreover, the displayed error message is at the top of the page.
I will consider your solution when I have time. I let you know soon.
I have to add at relationship level (i.e on the image property of my main entity) anAssertNotNull() in addition to @AssertValid()
yep, that's why.
Moreover, the displayed error message is at the top of the page.
Not really ergonomic but same for me in the case of Assert only on the file :/
However with my expression assert, the error is displayed at the right place.
I will consider your solution when I have time. I let you know soon.
Ok, you can also manage it with defining the same kind of tests in an AssertCallback()
@laurent-bientz
I introduced your assertion to validate my images. It works perfectly. I think that this whole conversation gives a correct method for image validation when using VichUploader bundle. In my next comment I propose a summary in order to close this issue.
@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;
}
Closing because this issue is too old to be relevant. Thanks!
Most helpful comment
@javiereguiluz
Thanks to @laurent-bientz and its solution for image validation, I propose that we close this issue (and remove the
bugandunconfirmedlabels).Here is a summary for image validation when the image is mandatory (non-nullable).
Considering the following entity (getters and setters are not given):
Config file + front validation :
Back validation: