更改用户他/她的密码

时间:2018-04-04 10:34:57

标签: symfony4

我尝试向用户发送电子邮件,以便他可以重置密码, 我使用swiftmailer生成了一个事件,但是当我在电子邮件表单中键入电子邮件地址向用户发送电子邮件时,我遇到了以下错误: 当我输入数据库中存在的电子邮件时:error =已经发送电子邮件

当我输入数据库中不存在的电子邮件时:error =在null上调用成员函数getUsername()。

拜托,我需要帮助

class ChangepasswordController extends Controller
{
public function sendMailAction(Request $request, EventDispatcherInterface 
$eventDispatcher, $email)
{
    $user = new User();
    $form = $this->createForm(SendmailType::class, $user);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        try {
            $user = $this->getDoctrine()->getRepository(User::class)
            ->findOneBy(array('email' => $email));


        } catch (ExceptionInterface $e) {
            $this->addFlash('danger', "Cet email n'existe pas.");
        }
        $event = new GenericEvent($user);
        $eventDispatcher->dispatch(Events::USER_RESETPASSWORD , $event);

        return $this->redirect('connexion');


    }
    return $this->render(
        'security/changePassword.html.twig',
        array('form' => $form->createView())
    );

}
}

我的活动:

class EventResetpassword implements EventSubscriberInterface
{

private $mailer;
private $sender;
private $twig;

public function __construct(\Swift_Mailer $mailer, $sender, Environment $twig)
{
    $this->mailer = $mailer;
    $this->sender = $sender;
    $this->twig   = $twig;
}

public static function getSubscribedEvents()
{
    return [
        Events:: USER_RESETPASSWORD => 'userResetPassword'

    ];
}


/**
 * @param GenericEvent $event
 * @throws \Twig_Error_Loader
 * @throws \Twig_Error_Runtime
 * @throws \Twig_Error_Syntax
 */
public function userResetPassword(GenericEvent $event): void
{
    /** @var User $user */

    $user = $event->getSubject();
    $username = $user->getUsername();
    $message = (new \Swift_Message())
        ->setSubject($username)
        ->setTo($user->getEmail())
        ->setFrom($this->sender)
        ->setBody($this->twig->render('security/sendemail.html.twig', [
            'username' => $username
        ]));

    $this->mailer->send($message);

}

}

3 个答案:

答案 0 :(得分:1)

其中一个问题是,当没有用户使用电子邮件地址且没有抛出异常时,findOnyBy将返回null。

你必须做空检查:

$user = $this->getDoctrine()->getRepository(User::class)
            ->findOneBy(array('email' => $email));


if(null !== $user){
    $event = new GenericEvent($user);
    $eventDispatcher->dispatch(Events::USER_RESETPASSWORD , $event);

    return $this->redirect('connexion');
}
$this->addFlash('danger', "Cet email n'existe pas.");

其他问题是$email无法通过魔法注入你的行动,如果它不是你路线的参数。 由于您使用的是表单,因此必须从表单中获取数据。 $form->getData()在您的情况下,这将返回带有电子邮件集的User实例。这也是错误的,因为它不是用户所以它没有任何意义。您应该使用只有电子邮件的简单值对象/ DTO,这样可以避免混淆。

你应该真正阅读有关symfony中表单的文档:

https://symfony.com/doc/current/forms.html

https://symfony.com/doc/current/best_practices/forms.html

这也是很好的阅读,关于如何做到(你应该这样做:))

https://blog.martinhujer.cz/symfony-forms-with-request-objects/

还有一件事情永远不会使用ExceptionInterface,只有Exceptions你可以,除此之外,这样你就可以抑制意想不到的东西,并且以后会遇到很难解决的问题。

答案 1 :(得分:0)

I update my Code: 

  /**
 * @Route("/send-mail", name="send_mail")
 * @Method({"GET", "POST"})
 * @param Request $request
 * @return Response
 */
public function sendMailAction(Request $request, EventDispatcherInterface $eventDispatcher, GenerateToken $token)
{
    $form = $this->createForm(SendMailType::class);
    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {
        $email = $form->get('email')->getData();
        $em = $this->getDoctrine()->getManager();
        /** @var User $user */
        if ($user = $em->getRepository(User::class)->findOneByEmail($email)) {
            $user->setToken($token->generateToken());
            $em->persist($user);
            $em->flush();

            $event = new GenericEvent($user);
            $eventDispatcher->dispatch(Events::USER_RESETPASSWORD, $event);
        }
        return $this->redirectToRoute('check_email');

    }

    return $this->render('security/change_password.html.twig', [
        'form' => $form->createView(),
    ]);

}

答案 2 :(得分:0)

  /**
 * @Route("/change-password/{token}", name="change_password")
 * @Method={"POST"}
 * @param Request $request
 * @param string $token
 * @return Response
 */
public function changePasswordAction(Request $request, UserPasswordEncoderInterface $passwordEncoder,  $token)
{
    $em = $this->getDoctrine()->getManager();
    /** @var User $user */
    $user = $em->getRepository(User::class)->findOneByToken($token);
    $form = $this->createForm(ResetPasswordType::class);

    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {

    $password = $form->get('password')->getData();
    $passwordencoded = $passwordEncoder->encodePassword($user, $password);
    $user->setPassword($passwordencoded);
    $user->setToken(null);
    $em = $this->getDoctrine()->getManager();
    $em->persist($user);
    $em->flush();

    $this->addFlash(
            'success',
            'votre mot de passe est bien réinitialisé vous pouvez vous connecter'
        );
    return $this->redirectToRoute('login');

    }

    return $this->render('security/reset_password.html.twig', [
        'form' => $form->createView(),
    ]);
}

类GenerateToken {

public function generateToken()
{
    $token= md5(uniqid(rand(), true));
    return $token;
}

}