課題
パスワードの変更やクレジットカードの削除など、システム上、重要な変更をする場合は、ログインをしている状態でも、本人確認のために、再度、パスワードを確認したい。
バリデーションを眺めていたら、目的に合致する機能があったので、使ってみました。
TL;DR
こちらも、ズバリ、バリデーションとして、UserPasswordが用意されている。
こちらを使うと、現在ログイン済みのアカウントのパスワードとチェックをしてくれるというもの。
フォームクラスとして、以下のように定義して使います。
コントローラとTwigテンプレも掲載します。
App/Form/PasswordChangeType.php
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
class PasswordChangeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('oldPassword', PasswordType::class, [
'constraints' => [
new UserPassword([
'message' => '正しいパスワードを設定してください。'
])
]
])
->add('newPassword', RepeatedType::class, [
'type' => PasswordType::class,
'required' => true,
'invalid_message' => '再入力されたパスワードと一致しません。',
'constraints' => [
new NotBlank([
'message' => 'パスワードを設定指定ください。',
]),
new Length([
'min' => 6,
'minMessage' => 'パスワードは、{{ limit }}文字以上で設定してください。',
// max length allowed by Symfony for security reasons
'max' => 100,
'maxMessage' => 'パスワードは、{{limit}}文字以内で設定してください。'
]),
],
])
;
}
}
App/Controller/changePasswordController.php
/**
* @Route("/password/change", name="password_change")
* @param Request $request
* @param UserPasswordEncoderInterface $passwordEncoder
* @param Security $security
* @return \Symfony\Component\HttpFoundation\Response
*/
public function changePassword(int $id, Request $request, UserPasswordEncoderInterface $passwordEncoder, Security $security)
{
$email = $security->getUser()->getUsername();
/** @var User $user */
$user = $this->getDoctrine()->getRepository(User::class)->findOneBy(['email' => $email]);
$form = $this->createForm(UserPasswordType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user->setPassword(
$passwordEncoder->encodePassword(
$user,
$form->get('newPassword')->getData()
)
);
$this->getDoctrine()->getManager()->flush();
$this->addFlash('success', 'パスワードを変更しました。');
}
return $this->render('changePassword/password.html.twig', [
'passwordForm' => $form->createView()
]);
}
templates/changePassword/password.html.twig
<div class="container">
<div class="row justify-content-center">
<div class="col-4">
{{ form_start(passwordForm) }}
{{ form_row(passwordForm.oldPassword, {label:'現在のパスワード'}) }}
{{ form_row(passwordForm.newPassword.first, {label:'新しいパスワード'}) }}
{{ form_row(passwordForm.newPassword.second, {label:'新しいパスワード再入力'}) }}
<button class="btn btn-primary" name="confirm" type="submit"><i class="fas fa-check fa-fw mr-2"></i>変更する</button>
{{ form_end(passwordForm) }}
</div>
</div>
</div>
以下が実際の動作