【发布时间】:2018-12-02 21:23:48
【问题描述】:
我正在更新我的用户实体。它是在其唯一电子邮件上定义的唯一实体。 不幸的是,在更新我的实体时,由于此电子邮件唯一验证规则,我触发了验证错误。
我一直在尝试将 $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();
}
}
}
【问题讨论】:
-
UniqueEmail 是自定义约束验证,对吗?你能展示这个约束验证的代码吗?另外,请显示错误。
-
您可能需要在 try/catch 中使用 UniqueConstraintViolationException ,我建议您阅读此内容:stackoverflow.com/questions/3967226/…
-
@FranckGamess 感谢您的评论,我已经编辑了发布 UniqueEmailValidator.php 文件的问题。触发的消息是我在 UniqueEmail.php 中的同一验证器文件夹中设置的消息。
-
@pbenard 谢谢,我知道这种情况是在调用 flush() 时发生的。这可以与表单验证一起使用吗?
-
不,我不认为,您只需将刷新包装在 try\catch 中,如果错误被捕获,则使用 $form->addError 手动添加错误,并返回表单像这样。
标签: php symfony doctrine-orm symfony4