Skip to content

Instantly share code, notes, and snippets.

@cirykpopeye
Last active December 11, 2023 05:09
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cirykpopeye/ceffcb58f5104e20710f0812940cac5a to your computer and use it in GitHub Desktop.
Save cirykpopeye/ceffcb58f5104e20710f0812940cac5a to your computer and use it in GitHub Desktop.
Easy Image upload with Symfony 4
<?php
/**
* Created by PhpStorm.
* User: ciryk
* Date: 11/07/18
* Time: 19:23
*/
namespace App\Service;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FileUploader
{
private $targetDirectory;
/**
* FileUploader constructor.
* @param $targetDirectory
*/
public function __construct($targetDirectory)
{
$this->targetDirectory = $targetDirectory;
}
public function upload(UploadedFile $file)
{
$filename = md5(uniqid()) . '.' . $file->guessExtension();
$file->move($this->targetDirectory, $filename);
return $filename;
}
}
<?php
/**
* Created by PhpStorm.
* User: ciryk
* Date: 11/07/18
* Time: 18:56
*/
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
* @ORM\Table(name="image")
*/
class Image
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
private $id;
/**
* @var string $file
* @ORM\Column(type="string")
*
* @Assert\NotBlank(message="Please, upload an image first.")
* @Assert\File(mimeTypes={ "image/png", "image/jpeg", "image/jpg" })
*/
private $file;
/**
* @ORM\Column(type="string", nullable=true)
*/
private $alt;
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
*/
public function setId($id): void
{
$this->id = $id;
}
/**
* @return string
*/
public function getFile()
{
return $this->file;
}
/**
* @param string $file
*/
public function setFile($file)
{
if ($file) {
$this->file = $file;
}
}
/**
* @return mixed
*/
public function getAlt()
{
return $this->alt;
}
/**
* @param mixed $alt
*/
public function setAlt($alt)
{
$this->alt = $alt;
}
}
<?php
/**
* Created by PhpStorm.
* User: ciryk
* Date: 9/12/18
* Time: 21:27
*/
namespace App\Form;
use App\Entity\Image;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ImageType extends FileType
{
private $imagePath;
/**
* ImageType constructor.
* @param $imagePath
*/
public function __construct($imagePath)
{
$this->imagePath = $imagePath;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->addModelTransformer(new CallbackTransformer(
function(Image $image = null) {
if ($image instanceof Image) {
return new File($this->imagePath . $image->getFile());
}
},
function(UploadedFile $uploadedFile = null) {
if ($uploadedFile instanceof UploadedFile) {
$image = new Image();
$image->setFile($uploadedFile);
return $image;
}
}
));
}
public function getBlockPrefix()
{
return 'image';
}
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults([
'required' => false
]);
}
}
<?php
/**
* Created by PhpStorm.
* User: ciryk
* Date: 9/12/18
* Time: 21:28
*/
namespace App\EventListener;
use App\Entity\Image;
use App\Service\FileUploader;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class ImageUploadListener
{
private $uploader;
/**
* ImageUploadListener constructor.
* @param $uploader
*/
public function __construct(FileUploader $uploader)
{
$this->uploader = $uploader;
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$this->uploadFile($entity);
}
public function preUpdate(PreUpdateEventArgs $args)
{
$entity = $args->getEntity();
$this->uploadFile($entity);
}
private function uploadFile($entity)
{
if (!$entity instanceof Image) {
return;
}
$file = $entity->getFile();
if ($file instanceof UploadedFile) {
$filename = $this->uploader->upload($file);
$entity->setFile($filename);
}
}
}
@carteur007
Copy link

please
how to autowiring arg $imagePath
goodAutowiringArg*

@cirykpopeye
Copy link
Author

please
how to autowiring arg $imagePath
goodAutowiringArg*

Hi @carteur007 You will need to add this as a service. F.e. in config/services.yaml add the following:

App\Form\ImageType:
  arguments:
    - '%kernel.project_dir%/public/uploads/'

This will turn your form type class into a service, you can inject other services inside your constructor or you can add simple strings like above, the %kernel.project_dir% points to the root of you application.

This should work, if you have any problems let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment