Symfony 4,编辑用户实体并保存新密码

时间:2019-03-25 23:43:38

标签: php symfony4

我执行了make:crud命令,为实体用户生成了一些文件。

所有功能都像一个超级按钮,但是编辑用户时我遇到一个问题。 编辑用户时,我可以:

  • 更改密码并保存

  • 请勿修改密码并保存

从生成的用户“编辑”控制器中:

/**
 * @Route("/{id}/edit", name="user_edit", methods={"GET","POST"})
 */
public function edit(Request $request, User $user): Response
{
    $form = $this->createForm(UserType::class, $user);
    $form->handleRequest($request);

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

        // HERE : How can I check if the password was changed ? 

        $this->getDoctrine()->getManager()->flush();

        return $this->redirectToRoute('user_index', [
            'id' => $user->getId(),
        ]);
    }

    return $this->render('user/edit.html.twig', [
        'user' => $user,
        'form' => $form->createView(),
        'title' => 'edit userr'
    ]);
}

如何检查密码是否已更改?用户变量包含新的密码值...

如果密码是新密码,则必须使用编码器服务。如果没有,我只需要用新数据更新用户

1 个答案:

答案 0 :(得分:2)

为此,在您的User中拥有一个未写入数据库的类变量将很有帮助。然后,您可以在表单中使用此变量临时存储更新的密码,然后对其进行编码和删除。这就是UserInterface中的eraseCredentials()方法的目的。

例如,在您的用户中,您可以拥有

class User implements UserInterface
{
    private $plainPassword;

    // ...

    public function setPlainPassword(string $plainPassword)
    {
        $this->plainPassword = $plainPassword;
    }

    public function getPlainPassword()
    {
        return $this->plainPassword;
    }

    public function eraseCredentials()
    {
        $this->plainPassword = null;
    }
}

请注意private $plainPassword如何没有任何ORM注释,这意味着它不会存储在数据库中。但是,您可以使用验证约束,例如如果要确保密码的长度最小或一定复杂度。您仍然需要存储加密密码的原始密码字段。

然后您将此字段添加到用户更新表单,而不是实际密码字段。然后,您只能在控制器中检查是否填写了新的plainPassword字段,然后读取该值,对其进行编码并替换实际的密码字段。

if ($form->isSubmitted() && $form->isValid()) {
    $user = $form->getData();
    if ($user->getPlainPassword() !== null) {
        $user->setPassword($this->userPasswordEncoder->encode(
            $user->getPlainPassword(),
            $user
        );
    }

    // ...

执行此操作而不向用户添加此“帮助程序”属性的另一种方法是使用未映射的表单字段:

# UserForm
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        // ...
        ->add('plainPassword', PasswordType::class, ['mapped' => false])
    ;
}

控制器将看起来类似,只有从未映射字段而不是从用户获取数据:

 $form->get('plainPassword')->getData();