Как обновить уникальное поле сущности с помощью формы Symfony 4 - PullRequest
0 голосов
/ 23 июня 2018

Я обновляю свою пользовательскую сущность.Это уникальная сущность, определенная в ее уникальном электронном письме.К сожалению, при обновлении моей сущности я вызываю ошибку проверки из-за этого уникального правила проверки электронной почты.

Я пытался передать $ user в форму, чтобы убедиться, что он считает его пользователемобновить, но не повезло.

Это форма Ajax.

Любая идея, как обойти это, пожалуйста?

Пользовательский объект

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

/**
 * @var string $email
 * @ORM\Column(type="string", length=254, nullable=false)
 * @Assert\Email()
 * @Assert\NotBlank
 * @AcmeAssert\UniqueEmail
 */
private $email;

/**
 * @ORM\Column(type="string", length=25, nullable=true)
 */
private $username;
// and so on

Мой контроллер:

/**
 * @Route("/profile", name="profile")
*/
public function profile()
{
    $user = $this->getUser();
    $formAccount = $this->updateUserAccountForm( $user );

    return $this->render('platform/user/profile.html.twig',
        array(
            'user' => $user,
            'form_account' => $formAccount->createView()
        )
    );
}

/**
 * @Route("/profile/updateAccount", name="updateUserAccount", methods={"POST"})
 */
public function updateUserAccount(Request $request, UserPasswordEncoderInterface $passwordEncode)
{
    if (!$request->isXmlHttpRequest()) {
        return new JsonResponse(array('message' => 'Forbidden'), 400);
    }

    // Build The Form
    $user = $this->getUser();

    $form = $this->updateUserAccountForm($user);
    $form->handleRequest($request);

    if ($form->isValid()) {
        $user_form = $form->getData();

        // Check if the password is = to DB
        $current_password = $passwordEncoder->encodePassword($user, $user_form->getPlainPassword());

        if($user->getPassword() != $current_password){
            return new JsonResponse(['error' => 'wrong password!']);
        }

        // Encode the password (We could also do this via Doctrine listener)
        $password = $passwordEncoder->encodePassword($user_form, $user_form->getPlainPassword());
        $user_form->setPassword($password);

        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->merge($user_form);
        $entityManager->flush();

        $em = $this->getDoctrine()->getManager();
        $em->persist($user_form);
//            $em->flush();

        return new JsonResponse(array('message' => 'Success!'), 200);
    }

    $errors = [];
    foreach ($form->getErrors(true, true) as $formError) {
        $errors[] = $formError->getMessage();
    }
    $errors['userid'] = $user->getId();
    $errors['user'] = $user->getUsername();
    return new JsonResponse($errors);
}

/**
 * Creates a form to update user account.
 *
 * @param User $entity The entity
 *
 * @return \Symfony\Component\Form\FormInterface The form
 */
private function updateUserAccountForm(User $user)
{
    $form = $this->createForm( AccountType::class, $user,
        array(
            'action' => $this->generateUrl('updateUserAccount'),
            'method' => 'POST',
        ));

    return $form;
}

И AccountType.php

class AccountType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('username', TextType::class)
        ->add('email', EmailType::class, array(
            'required' => true,
            'constraints' => array(
                new NotBlank(),
            )))
        ->add('password', PasswordType::class, array(
            'required' => true
            ))
        ->add('plainPassword', RepeatedType::class, array(
            'type' => PasswordType::class,
            'invalid_message' => 'The new password fields must match.',
            'required' => false,
            'first_options'  => array('label' => 'New Password'),
            'second_options' => array('label' => 'Confirm New Password')
        ))
        ->add('save', SubmitType::class, array('label' => 'Save ->'));
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        // enable/disable CSRF protection for this form
        'csrf_protection' => true,
        // the name of the hidden HTML field that stores the token
        'csrf_field_name' => '_token',
        // an arbitrary string used to generate the value of the token
        // using a different string for each form improves its security
        'csrf_token_id'   => 'reset_item',
        'data_class' => User::class
    ));
}
}

Вызов ajax возвращает сериализованную форму.Форма была создана в профиле и работает хорошо.Я получаю сообщение об ошибке формы при вызове '$ form-> isValid ()'

Я пытался все, чтобы передать $ user в типе формы, чтобы Symfony понял, что он основан на предварительномСуществующий пользователь.но не повезло.

Любая помощь приветствуется, спасибо!

РЕДАКТИРОВАТЬ: Вот мой пользовательский класс UniqueEmail Validator:

class UniqueEmailValidator extends ConstraintValidator
{
    /**
     * @var EntityManager
     */
    protected $em;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->em = $entityManager;
    }

    public function validate($value, Constraint $constraint)
    {
        // Do we have a pre registered user in DB from email form landing page?
        $userRepository = $this->em->getRepository(User::class);
        $existingUser = $userRepository->findOneByEmail($value);

        if ($existingUser && $existingUser->getIsActive()) {
            $this->context->buildViolation($constraint->message)
                ->setParameter('{{ string }}', $value)
                ->addViolation();
        }
    }
}

1 Ответ

0 голосов
/ 25 июня 2018

Из того, что я вижу, когда вы отправляете форму, ограничение UniqueEmail , которое вы установили в поле email , пытается проверить отправленное значение с определенным вами правилом. Допустим, вы хотите обновить только имя пользователя , форма будет отправлена ​​с текущим значением поля email , хранящимся в базе данных. И, конечно, это вызовет ошибку проверки.

Как правило, лучше установить уникальное ограничение на столбец email в таблице user . Таким образом, вы сможете правильно обновить вашу сущность Пользователь , даже если вы не измените поле email . А также вы не сможете создать нового пользователя в базе данных с тем же адресом электронной почты, что и у существующего пользователя. Я думаю, это то, что вы хотите.

Доктрина может помочь вам достичь этого.

С @ UniqueConstraint на уровне объекта:

<?php
/**
 * @Entity
 * @Table(name="user_table",uniqueConstraints= {@UniqueConstraint(name="search_idx", columns={"email"})})
 */
class User implements UserInterface, \Serializable
{
}

С @ Column на уровне поля с уникальным атрибутом (я предпочитаю этот, но зависит от случая):

/**
 * @var string $email
 * @ORM\Column(type="string", length=32, unique=true, nullable=false)
 * @Assert\Email()
 * @Assert\NotBlank
 */
private $email;

Просто взгляните и попробуйте посмотреть, решит ли это вашу проблему.

...