在Symfony2 FOSUserBundle中,如何向表单抛出自定义错误消息

时间:2016-05-04 23:10:13

标签: symfony fosuserbundle

在FOSUserBundle中,我已经覆盖了ChangePasswordController - > changePasswordAction所以我可以保存旧密码以防止用户重复使用它们。

我已经完成了所有工作,但如果用户尝试使用旧的存档密码进行更新,我就不知道如何向表单发送自定义错误消息。

这是我的changePasswordAction,我的更改都在if ($form->isValid()) { ... }

public function changePasswordAction(Request $request)
{
    $user = $this->getUser();
    if (!is_object($user) || !$user instanceof UserInterface) {
        throw new AccessDeniedException('This user does not have access to this section.');
    }

    /** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
    $dispatcher = $this->get('event_dispatcher');

    $event = new GetResponseUserEvent($user, $request);
    $dispatcher->dispatch(FOSUserEvents::CHANGE_PASSWORD_INITIALIZE, $event);

    if (null !== $event->getResponse()) {
        return $event->getResponse();
    }

    /** @var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
    $formFactory = $this->get('fos_user.change_password.form.factory');

    $form = $formFactory->createForm();
    $form->setData($user);

    $form->handleRequest($request);

    if ($form->isValid()) {
        /** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */
        $userManager = $this->get('fos_user.user_manager');

        if (0 !== strlen($password = $form->getData()->getPlainPassword())) {
            $newPassword = $userManager->getEncodedPassword($user, $password);

            // get the number of Archived Passwords to be saved
            $numArchives = 0;
            $company = $user->getCompany();
            if (!empty($company)) {
                $passwordAllowedSaves = $company->getPasswordAllowedSaves();
                if (!empty($passwordAllowedSaves)) {
                    $numArchives = $passwordAllowedSaves;
                }
            }

            // check archived passwords
            if ($numArchives > 0) {
                $oldestArchive = null;
                $passwordAlreadyArchived = false;

                $archives = $user->getArchives();
                foreach ($archives as $archive) {
                    // track the oldest archive
                    if (empty($oldestArchive)) {
                        $oldestArchive = $archive;
                    } else {
                        if ($oldestArchive->getCreated() < $archive->getCreated()) {
                            $oldestArchive = $archive;
                        }
                    }

                    // check the newPassword is not archived
                    if ($newPassword == $archive->getPassword()) {
                        $passwordAlreadyArchived = true;
                    }
                }

                // if this is an archived password it can't be saved
                if ($passwordAlreadyArchived) {
                    die('nope');
                    //$event = new FormEvent($form, $request);
                    //$dispatcher->dispatch(FOSUserEvents::CHANGE_PASSWORD_SUCCESS, $event);
                } else {
                    // save password in a new Archive
                    $entityManager = $this->getDoctrine()->getManager();
                    $archive = new Archive();
                    $archive->setPerson($user)
                        ->setPassword($newPassword)
                        ->setCreated(new \DateTime());

                    $entityManager->persist($archive);
                    $entityManager->flush();

                    // Make sure that there are not too many saved
                    if (count($archives) + 1 > $numArchives) {
                        $user->removeArchive($oldestArchive);
                    }
                }
            }
        }

        $event = new FormEvent($form, $request);
        $dispatcher->dispatch(FOSUserEvents::CHANGE_PASSWORD_SUCCESS, $event);

        $userManager->updateUser($user);

        if (null === $response = $event->getResponse()) {
            $url = $this->generateUrl('person_show', array('id' => $user->getId()));
            $response = new RedirectResponse($url);
        }

        $dispatcher->dispatch(FOSUserEvents::CHANGE_PASSWORD_COMPLETED, new FilterUserResponseEvent($user, $request, $response));

        return $response;
    }

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

如果用户输入旧密码,那么就死掉(&#39; nope&#39;);被执行。我不确定要替换什么,所以我可以在表单中得到一个好消息。

1 个答案:

答案 0 :(得分:0)

我建议通过覆盖它来为表单添加自定义约束。有关覆盖表单here的更多信息。

顺便说一句,你没有必要覆盖这个控制器。你可以用其他几种方式做到这一点。

  1. FOSUserEvents::CHANGE_PASSWORD_SUCCESS事件创建一个侦听器,并在处理时存档旧密码。
  2. 为Doctirne的postUpdate实体事件创建一个监听器。 (更多信息here