Reputation: 372
I am New to Symfony 3 and I have an Issue when I try to activate my account. I extend my User Entity from FOSUserBundle. I have activated the confirmation system of FOS_User. Furthermore, when a user register into my app, he must upload a file. To do this, I created a FileUploader service and a ImageUploadListener listener. The problem is when I click on my activation link from my gmail's email, I get the following error:
Uncaught PHP Exception Symfony\Component\Debug\Exception\ContextErrorException: "Notice: Undefined variable: fileName" at /home/clement/Rendu/tech-web/src/UserBundle/EventListener/ImageUploadListener.php line 49
Could you help me ? Thank you in advance from a french dev with a big headache !
PS: I followed this tutorial to implement my file upload functionality.
User.php
namespace UserBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
* @ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", length=255)
*
* @Assert\NotBlank(message="Please enter your phone.", groups={"Registration", "Profile"})
* @Assert\Length(
* min=3,
* max=255,
* minMessage="The phone is too short.",
* maxMessage="The phone is too long.",
* groups={"Registration", "Profile"}
* )
*/
protected $phone;
/**
* @ORM\Column(type="string")
*
* @Assert\NotBlank(message="Please, upload a file.")
* @Assert\File(mimeTypes={ "application/pdf", "image/jpeg" })
*/
private $image;
public function __construct()
{
parent::__construct();
// your own logic
$this->roles = array('ROLE_USER');
}
public function getPhone() {
return $this->phone;
}
public function setPhone($phone) {
$this->phone = $phone;
}
public function setImage($image)
{
$this->image = $image;
return $this;
}
public function getImage()
{
return $this->image;
}
}
RegistrationType.php
namespace UserBundle\Form;
use UserBundle\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;
class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('phone')
->add('image', FileType::class);
}
public function getParent()
{
return 'FOS\UserBundle\Form\Type\RegistrationFormType';
// Or for Symfony < 2.8
// return 'fos_user_registration';
}
public function getBlockPrefix()
{
return 'app_user_registration';
}
// For Symfony 2.x
public function getName()
{
return $this->getBlockPrefix();
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => User::class,
));
}
}
FileUploader.php
namespace UserBundle\Service;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FileUploader
{
private $targetDir;
public function __construct($targetDir)
{
$this->targetDir = $targetDir;
}
public function upload(UploadedFile $file)
{
$fileName = md5(uniqid()).'.'.$file->guessExtension();
$file->move($this->getTargetDir(), $fileName);
return $fileName;
}
public function getTargetDir()
{
return $this->targetDir;
}
}
ImageUploadListener
namespace UserBundle\EventListener;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use UserBundle\Entity\User;
use UserBundle\Service\FileUploader;
use Symfony\Component\HttpFoundation\File\File;
class ImageUploadListener
{
private $uploader;
private $fileName;
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)
{
// upload only works for User entities
if (!$entity instanceof User) {
return;
}
$file = $entity->getImage();
// only upload new files
if ($file instanceof UploadedFile) {
$fileName = $this->uploader->upload($file);
}
$entity->setImage($fileName);
}
}
services.yml
parameters:
#parameter_name: value
services:
_defaults:
autowire: true
autoconfigure: true
public: false
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
app.form.registration:
class: UserBundle\Form\RegistrationType
tags:
- { name: form.type, alias: app_user_registration }
UserBundle\Service\FileUploader:
arguments:
$targetDir: '%images_directory%'
UserBundle\EventListener\ImageUploadListener:
tags:
- { name: doctrine.event_listener, event: prePersist }
- { name: doctrine.event_listener, event: preUpdate }
config.yml
fos_user:
db_driver: orm
firewall_name: main
user_class: UserBundle\Entity\User
service:
mailer: fos_user.mailer.twig_swift
from_email:
address: "%mailer_user%"
sender_name: "%mailer_user%"
registration:
form:
type: UserBundle\Form\RegistrationType
confirmation:
enabled: true
template: '@FOSUser/Registration/email.txt.twig'
from_email:
address: "%mailer_user%"
sender_name: "%mailer_user%"
profile:
form:
type: UserBundle\Form\EditType
Upvotes: 2
Views: 96
Reputation: 1181
Your event is launched each time you save an user. When you activate the user account you update the user with doctrine in the database so the preUpdate event is call.
To avoid the notice you should do this :
// only upload new files
if ($file instanceof UploadedFile) {
$fileName = $this->uploader->upload($file);
$entity->setImage($fileName);
}
And to avoid to call each time your uploader you have to check if the file is already upload or override the register action to upload it instead of use a doctrine event to do this
Upvotes: 1