问题
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?
回答1:
$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
来源:https://stackoverflow.com/questions/41488108/symfony-file-upload-in-edit-form