I'm looking to refactor some code to avoid repetition ;) Bundles used:
- symfony 6.0.7
- vich/uploader-bundle 1.19
- easycorp/easyadmin-bundle 4.1.1
I have a Content entity where all content types are defined. The MyImage property is a OneToOne relationship to an Image utility entity so as not to repeat the code.
When I try to display the edit (or create) page of a Page, the following error is raised: Mapping not found for field " myImage_image".
Here are the files in question.
The Content entity:
<?php
namespace App\Entity\Content;
use App\Entity\Media\Image;
use App\Repository\Content\ContentRepository;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
#[ORM\Entity(repositoryClass: ContentRepository::class)]
#[ORM\Table(name: 'content')]
#[ORM\InheritanceType('JOINED')]
#[ORM\DiscriminatorColumn(name: 'type', type: 'string')]
#[ORM\DiscriminatorMap([
'page' => Page::class,
// ...
])]
#[Vich\Uploadable]
abstract class Content
{
use SoftDeleteableEntity;
use TimestampableEntity;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id = null;
// ...
#[ORM\OneToOne(targetEntity: Image::class, cascade: ['persist', 'remove'])]
private Image $myImage;
public function __construct()
{
$this->myImage = new Image();
}
// ...
public function getMyImage(): Image
{
return $this->myImage;
}
public function setMyImage(Image $myImage): self
{
$this->myImage = $myImage;
return $this;
}
}
The Image entity:
<?php
namespace App\Entity\Media;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Timestampable\Traits\Timestampable;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
#[ORM\Entity]
#[Vich\Uploadable]
class Image
{
use Timestampable;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id;
#[Vich\UploadableField(mapping: 'content', fileNameProperty: 'imageName')]
private ?File $image;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private ?string $imageName;
/**
* @return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @param int|null $id
*/
public function setId(?int $id): void
{
$this->id = $id;
}
/**
* @return File|null
*/
public function getImage(): ?File
{
return $this->image;
}
/**
* @param $image
*
* @return $this
*/
public function setImage($image): self
{
// VERY IMPORTANT:
// It is required that at least one field changes if you are using Doctrine,
// otherwise the event listeners won't be called and the file is lost
if ($image) {
// if 'updatedAt' is not defined in your entity, use another property
$this->updatedAt = new \DateTime('now');
}
return $this;
}
/**
* @return string|null
*/
public function getImageName(): ?string
{
return $this->imageName;
}
/**
* @param string|null $imageName
*
* @return $this
*/
public function setImageName(?string $imageName): self
{
$this->imageName = $imageName;
return $this;
}
}
The Vich config:
vich_uploader:
db_driver: orm
metadata:
type: attribute
mappings:
content:
uri_prefix: /uploads/content
upload_destination: '%kernel.project_dir%/public/uploads/content'
namer: Vich\UploaderBundle\Naming\SmartUniqueNamer
directory_namer:
service: Vich\UploaderBundle\Naming\CurrentDateTimeDirectoryNamer
options:
date_time_format: 'Y' # will create directory "2018/23/09" for curent date "2018-09-23"
date_time_property: createdAt # see above example
inject_on_load: false
delete_on_update: true
delete_on_remove: true
I'm sure it's a silly error but I can't seem to catch it.
Thanks in advance :)
Edit:
The CRUD Controller :
<?php
namespace App\Controller\Admin\Content;
use App\Entity\Content\Page;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\Field;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Vich\UploaderBundle\Form\Type\VichImageType;
class PageCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Page::class;
}
public function configureFields(string $pageName): iterable
{
// ...
yield Field::new('myImage.image')->setFormType(VichImageType::class);
// ...
}
}
I created an
ImageType
and used it in CRUD Controller: