简体   繁体   中英

Symfony File Upload In Edit Form

I have the following User Entity

/**
 * @ORM\Entity
 */
class User
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(name="name", type="string", length=100, nullable=false)
     */
    private $name;

    /**
     * @ORM\Column(type="string", name="picture", nullable=true)
     * @Assert\Image
     * @Assert\File(maxSize = "2M")
     */
    private $picture;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return User
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    public function setPicture($file)
    {
        $this->picture = $file;
        return $this;
    }

    public function getPicture()
    {
        return $this->picture;
    }
}

And here is my FormType

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name', TextType::class, [
            'label' => 'Name *',
            'attr' => [
                'class' => 'form-control placeholder-height'
            ],
            'label_attr' => [
                'class' => 'col-md-2 professional-attr'
            ],
            'constraints' => [
                new Assert\NotBlank(),
                new Assert\Length(['min' => 3, 'max' => 50])
            ]
        ]);

        $builder->add('picture', FileType::class, [
            'label' => 'Profile Picture',
            'attr' => [
                'class' => 'form-control filestyle',
                'data-iconName' => 'glyphicon glyphicon-camera',
                'data-buttonText' => null,
                'accept' => 'image/*'
            ],
            'label_attr' => [
                'class' => 'col-md-2 professional-attr'
            ],
            'data_class' => null
        ]);

        $builder->add('confirm', SubmitType::class, [
            'label' => 'SUBMIT',
            'attr' => [
                'class' => 'submit'
            ]
        ]);
    }

    public function setDefaultOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'UserBundle:User'
        ]);
    }
}

And here is the code in my controller

public function professionalEditAction(Request $request)
{
    $em = $this->get('doctrine.orm.entity_manager');
    $user = $em->getRepository('UserBundle:User')->findOneBy(['id' => $request->get('id')]);
    if (!$user) {
        throw $this->createNotFoundException('Invalid user or user does not exist');
    }
    $form = $this->createForm(Form\ProfessionalType::class, $user, [
        'method' => 'POST',
        'attr' => [
            'class' => 'form-horizontal',
            'novalidate' => 'novalidate',
            'accept' => 'image/*'
        ]
    ]);
    $form->handleRequest($request);
    $response = [];
    $response['params'] = [];
    if($form->isSubmitted() && $request->isXmlHttpRequest() && !$form->isValid()) {
        $data = $form->getData();
        foreach ($form as $child) {
            if (!$child->isValid()) {
                $response['status'] = 'error';
                $response['next_action'] = 'fix_error';
                $response['params'] = [];
                foreach ($child->getErrors() as $error) {
                    $response['errors'][$child->getName()][] = $error->getMessage();
                }
            }
        }
        return new JsonResponse($response);
    }
    if ($form->isSubmitted() && $form->isValid()) {
        $data = $form->getData();
        $file = $user->getPicture();
        if ($file instanceof UploadedFile) {
            $fileName = md5(uniqid()).'.'.$file->guessExtension();
            $file->move(
                $this->getParameter('profile.picture.attachment.dir'),
                $fileName
            );
            $data->setPicture($fileName);
        }
        $em->persist($data);
        $em->flush();
        $request->getSession()->getFlashBag()->add('success', 'User created successfully!');
        return $this->redirect($this->generateUrl('admin_professional_create'));
    }
    return $this->render('UserBundle:Admin:professional.edit.html.twig', [
        'form' => $form->createView(),
        'user' => $user
    ]);
}

It works perfectly if I upload a new file, but if I submit the input field empty, It changes to NULL value in DB which I do not want, what I want is, if user has previously uploaded the picture and leave it empty next time, just do not change the value of picture in the DB.

Note: I am not sure if this piece of Information helps, but I am submitting the form using Ajax and FormData, I have omitted part of the code to keep it simple.

What am I missing here?

$em->persist($data) is being called whether the file has been uploaded or not - try moving it within the if statement above it:

if ($file instanceof UploadedFile) {
     $fileName = md5(uniqid()).'.'.$file->guessExtension();
     $file->move(
        $this->getParameter('profile.picture.attachment.dir'),
        $fileName
    );
    $data->setPicture($fileName);
    $em->persist($data); // Place here
}

So that will only persist the object if a file has been uploaded.

Or , if there are other fields that can be changed on that form and the form always needs persisting regardless, can you set the data to the current user picture value before your if statement:

$file = $user->getPicture();
$data->setPicture($file); // Store the current value from the DB before overwriting below
if ($file instanceof UploadedFile) {
     $fileName = md5(uniqid()).'.'.$file->guessExtension();
     $file->move(
        $this->getParameter('profile.picture.attachment.dir'),
        $fileName
    );
    $data->setPicture($fileName);
}
$em->persist($data); // Leave here in original place

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM