Hello (excuse my English, not too confident with it)
I'm actually working on a Symfony website that display some spectacles' information.
For now, I need to add an image when I create one of them. I managed to do so with the help of this tutorial.
It basically works like this: I upload an image into site's directory and then send file's name to the entity (Store in a MySQL database). I can then display the image in spectacle's details.
The issue appeared when I want to edit a spectacle. I can't update the image's name. I have two only possibilities are to 1/not edit the entity, or to 2/change the image name and then get a random one that I can't display anymore (these names are usually like /tmp/phpWb8kwV)
My image is instantiate like this in the entity (in Spectacle.php):
/**
* @var string
*
* @ORM\Column(name="image", type="string", length=255)
* @Assert\NotBlank(message="Veuillez ajouter une image à votre spectacle.")
* @Assert\File(mimeTypes={ "image/png" })
*/
private $image;
And the FormType for the spectacle's form is made like this (in SpectacleType.php):
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('nom')
->add('lieu')
->add('dateSpectacle', null, array(
'label' => 'Date du spectacle',
))
->add('annee')
->add('image',FileType::class, array(
'label' => 'Image du spectacle',
'required' => false, //(Still need to provide a file to finalize the creation/edit)
));
}
And the controller to acces this page is made like this (in SpectacleController.php):
/**
* Creates a new spectacle entity.
*
* @Route("/new", name="admin_spectacle_new")
* @Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$spectacle = new Spectacle();
$form = $this->createForm('FabopBundle\Form\SpectacleType', $spectacle);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
//--------------------------------------------------------------------
$file = $spectacle->getImage();
$fileName = (md5(uniqid())).'.'.$file->guessExtension();
// moves the file to the directory where image are stored
$file->move(
$this->getParameter('img_directory'), //(Define in the service.yml)
$fileName
);
$spectacle->setImage($fileName); //(Don't know how to handle file names without this line)
//---------------------------------------------------------------------
$em->persist($spectacle);
$em->flush();
return $this->redirectToRoute('admin_spectacle_show', array('id' => $spectacle->getId()));
}
return $this->render('spectacle/new.html.twig', array(
'spectacle' => $spectacle,
'form' => $form->createView(),
));
}
The function that is routed to the edit view is approximatively the same, but i can't use
$spectacle->setImage($fileName);
There is two possibilities to solve this: I would like being able to update the new filename in the entity (with the other information) or being able to update the entity without changing filename.
I hope I was clear enough to explain my problem...
Thanks in advance for your responses.
I had this problem when trying to upload a PDF/TEXT.. file.
But for managing images, I advice you to use ComurImageBundle, it helps you a lot and your problem will be resolved.
It's very simple, you download the bundle like it's explained in this link.
Then you modify your code like this :
1/ Instantiation of your image in Spectacle.php (your image is stored in the DB like string)
/**
* @ORM\Column(type="string", nullable=true)
*/
private $image;
2/ Update your base ( php bin/console doctrine:schema:update --force)
3/ Add these functions to your Spectacle.php after updating your DB schema, these functions let you upload and stock your images under specific directory (web/uploads/spectacles) and don't forget to add this two libraries
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @Assert\File()
*/
private $file;
/**
* Sets file.
*
* @param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
/**
* Get file.
*
* @return UploadedFile
*/
public function getFile()
{
return $this->file;
}
/**
* @ORM\PrePersist
*/
public function preUpload()
{
if (null !== $this->file) {
$this->image = uniqid() . '.' . $this->file->guessExtension();
}
}
/**
* @ORM\PostPersist
*/
public function upload()
{
if (null === $this->file) {
return;
}
// If there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error
$this->file->move($this->getUploadRootDir(), $this->image);
}
public function getUploadDir()
{
return 'uploads/spectacles';
}
public function getBaseUrl()
{
$currentPath = $_SERVER['PHP_SELF'];
$pathInfo = pathinfo($currentPath);
return substr($pathInfo['dirname']."/", 1);
}
public function getUploadRootDir()
{
return $this->getBaseUrl() . $this->getUploadDir();
}
public function getWebPath()
{
return null === $this->image ? null : $this->getUploadDir() . '/' . $this->image;
}
public function getAbsolutePath()
{
return null === $this->image ? null : $this->getUploadRootDir() . '/' . $this->image;
}
4/ Modify the FormType (SpectacleType.php)like this
use Comur\ImageBundle\Form\Type\CroppableImageType;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('nom')
->add('lieu')
->add('dateSpectacle', null, array(
'label' => 'Date du spectacle',
))
->add('annee')
->add('image', CroppableImageType::class, array('label' => 'Image', 'required' => true,
'uploadConfig' => array(
'uploadUrl' => $myEntity->getUploadDir(), // required - see explanation below (you can also put just a dir path)
'webDir' => $myEntity->getUploadRootDir(), // required - see explanation below (you can also put just a dir path)
'fileExt' => '*.png', // required - see explanation below (you can also put just a dir path)
'showLibrary' => false,
),
'cropConfig' => array(
'minWidth' => 128,
'minHeight' => 128,
'aspectRatio' => true,
)
));
}
5/ Remove all these lines from your controller you won't need them
//--------------------------------------------------------------------
$file = $spectacle->getImage();
$fileName = (md5(uniqid())).'.'.$file->guessExtension();
// moves the file to the directory where image are stored
$file->move(
$this->getParameter('img_directory'), //(Define in the service.yml)
$fileName
);
$spectacle->setImage($fileName); //(Don't know how to handle file names without this line)
//---------------------------------------------------------------------
6/ That's it you can call the form of your image in new.html.twig and edit.html.twig, all will get well, try it please and notify me if there is any problem.
The solution was stupid ...
In fact, the controller to access the edit route didn't have those lines:
$em = $this->getDoctrine()->getManager();
...
$em->persist($spectacle);
$em->flush();
I need to finish this quickly. If i have more time later, i'll try to make it work with the ComurImageBundle.
Thank you for your help, i'll be more carefull next time ...