I have four pictures on my homepage banner and I'd like to be able to update them every now and then using a Symfony form.
I set up an Image Entity exactly as described in the Vich Uploader documentation (with updated At-Entity and everything)
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* Image
*
* @ORM\Table(name="app_image")
* @ORM\Entity
* @Vich\Uploadable
*/
class Image {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @Vich\UploadableField(mapping="dashboard", fileNameProperty="imageName", size="imageSize")
*
* @var File
*/
private $imageFile;
/**
* @ORM\Column(type="integer")
*
* @var integer
*/
private $imageSize;
/**
* @var string
* @ORM\Column(type="string", nullable=false)
*/
private $imageName;
/**
* @ORM\Column(type="datetime")
*
* @var \DateTime
*/
private $updatedAt;
/**
* @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*/
public function setImageFile(?File $image = null): void
{
$this->imageFile = $image;
if (null !== $image) {
$this->updatedAt = new \DateTimeImmutable();
}
}
public function getImageFile(): ?File
{
return $this->imageFile;
}
public function setImageName(?string $imageName): void
{
$this->imageName = $imageName;
}
public function getImageName(): ?string
{
return $this->imageName;
}
public function setImageSize(?int $imageSize): void
{
$this->imageSize = $imageSize;
}
public function getImageSize(): ?int
{
return $this->imageSize;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set updatedAt
*
* @param \DateTime $updatedAt
*
* @return Image
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* @return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
}
Since the four images already exist, I only added an action to update the images to my Controller
/**
* @Route("/uploadImage/{id}", name="appBundle_upload_image", requirements={"id" = "\d+"})
* @Security("is_granted('ROLE_ATTACHEMENT_ADMIN')")
*/
public function uploadAction(Request $request, $id){
$repository = $this->getDoctrine()->getRepository('AppBundle:Image');
$em = $this->getDoctrine ()->getManager ();
$image = $repository->findOneById($id);
$form = $this->createForm(UploadImageType::class, $image);
$form->handleRequest($request);
if ($form->isValid() ) {
$em->flush();
return $this->redirectToRoute('index');
}
return $this->render('AppBundle:Image:upload.html.twig', array(
'form' => $form->createView(),
'image' => $image,
));
}
I already have some pictures in my database table, so I can access the route to my controller action, the form that gets rendered contains simply this:
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('imageFile', VichImageType::class, [
'required' => false,
'allow_delete' => false,
'download_label' => '...',
'download_uri' => true,
'image_uri' => true,
]);
}
So as you can see, I didn't change a lot yet from the basic documentation. Anyway, when going to that route with e.g. ID 7, picture 7 is displayed under the download_uri and when dumping imageName or UpdatedAt, it's the same data as shown in my database table. But when I then try to upload a new picture which should replace the old one, I get an error saying
Entity AppBundle\Entity\Image@0000000075aa1d6c00000000789d890b is not managed. An entity is managed if its fetched from the database or registered as new through EntityManager#persist
or sometimes it goes through like a miracle and I get redirected, but nothing's changed in my database table, so the old picture didn't get replaced or anything.
I've search a lot and found a lot of solutions for the Entity not managed error, or not updating because no property changed. But none of them actually solved my problem.
Do you see anything in my code that could cause the problem?
UPDATE
I added @nifr 's setImageFile method to my Image Entity:
/**
* @param File|UploadedFile|null $imageFile
*
* @return $this
*/
public function setImageFile(File $imageFile = null)
{
$this->imageFile = $imageFile;
dump($imageFile);
if ($imageFile instanceof UploadedFile) {
$this->setFileSize($imageFile->getClientSize());
$this->setMimeType($imageFile->getClientMimeType());
$this->setOriginalName($imageFile->getClientOriginalName());
$this->updatedAt = new \DateTime();
}
return $this;
}
when dumping within the if condition, it's doing nothing, so apparently it doesn't recognize $imageFile as an instance of UploadedFile. However, when dumping before that (like in the copied code) it's dumping the following infos:
UploadedFile {#14 ▼
-test: false
-originalName: "Route.png"
-mimeType: "image/png"
-size: 13218
-error: 0
path: "/tmp"
filename: "phpQhWrTd"
basename: "phpQhWrTd"
pathname: "/tmp/phpQhWrTd"
extension: ""
realPath: "/tmp/phpQhWrTd"
aTime: 2018-02-05 19:03:12
mTime: 2018-02-05 19:03:12
cTime: 2018-02-05 19:03:12
inode: 311536
size: 13218
perms: 0100600
owner: 1001
group: 33
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
}
So apparently it IS from "UploadedFile". Any ideas?
Also what I tried, is dumping within my Controller:
public function uploadAction(Request $request, $id){
$repository = $this->getDoctrine()->getRepository('AppBundle:Image');
$em = $this->getDoctrine ()->getManager ();
$image = $repository->findOneById($id);
dump($image);
$form = $this->createForm(UploadImageType::class, $image);
$form->handleRequest($request);
if ($form->isValid() && $form->isValid() ) {
dump($image->getImageName());
$em->flush();
return $this->redirectToRoute('index');
}
return $this->render('AppBundle:Image:upload.html.twig', array(
'form' => $form->createView(),
'image' => $image,
));
}
Having the dump in the imageFile Setter I realized, that my dump in the controller contains the "old" imageName e.g. Name A but the Setter contains the "new" image name (from the image that's supposed to replace the old one), so actually the correct one. But it's never coming to an update.