用户使用FOSUserBundle更新配置文件时忽略密码

时间:2012-07-18 20:39:59

标签: symfony doctrine-orm fosuserbundle

我正在使用FOSUserBundle,我正在尝试创建一个允许用户更新其用户个人资料的页面。我面临的问题是,如果用户不想更改/更新密码,我的表单不需要用户重新输入密码。因此,当用户使用空密码提交表单时,数据库将使用空字符串进行更新,并且用户将无法登录。

如果未设置密码字段,如何让表单忽略更新密码字段?以下是我正在使用的代码。

$user = $this->get('security.context')->getToken()->getUser();

//user form has email and repeating password fields    
$userForm = $this->createForm(new UserFormType(), $user);

if ($request->getMethod() == 'POST') {
   $userForm->bindRequest($request);

   if($userForm->isValid()){
      //this will be be empty string in the database if the user does not enter a password
      $user->setPlainPassword($userForm->getData()->getPassword());
      $em->flush();
   }
}

我尝试了一些如下所示的内容,但这仍然是空的,因为bindRequest将空密码设置为用户

if($userForm->getData()->getPassword())
   $user->setPlainPassword($userForm->getData()->getPassword());

我也尝试过,但这会导致类似的情况并导致不必要的查询

if($userForm->getData()->getPassword())
   $user->setPlainPassword($userForm->getData()->getPassword());
else
   $user->setPlainPassword($user->getPlainPassword());

有没有优雅的方法来处理这个用例?

4 个答案:

答案 0 :(得分:6)

问题是在对密码进行控制之前将表单绑定到用户对象。 让我们分析一下你的代码片段。

执行以下操作

$user = $this->get('security.context')->getToken()->getUser();

会将现有用户加载到用户对象中。
现在您“构建”包含该数据的表单,如果收到帖子,您将把发布的数据带入上一个对象

$userForm = $this->createForm(new UserFormType(), $user);

if ($request->getMethod() == 'POST') {
   $userForm->bindRequest($request);

所以,在bindRequest上你已经将之前的密码丢失到对象(显然还没有进入数据库),如果这是空的话。从现在开始,每一项控制都是无用的。

在这种情况下,解决方案是在将表单字段的值绑定到基础对象之前,直接手动验证表单字段的值到$request对象。
您可以使用这段简单的代码片段

来完成此操作
$postedValues = $request->request->get('formName');

现在您必须验证密码值是否已填写

if($postedValues['plainPassword']) { ... }

其中plainPassword我想是我们感兴趣的领域的名称。

如果您发现此字段包含值(否则为分支),则您无需执行任何操作 否则您必须从用户对象中检索原始密码并将其设置为$request相应的值。
更新)否则,您可以从用户对象中检索密码,但由于该密码存储有hased值,因此您无法将其置于$request对象中,因为它将再次遭受散列。
你能做什么 - 我想 - 是一个array_pop直接进入$request对象并收起那些混乱的领域(plainPassword) 既然您已经完成了这些工作,就可以将发布的数据绑定到底层对象。

另一个解决方案(可能更好,因为你将一些业务逻辑从控制器移开)是使用prePersist钩子,但在概念上更先进。如果您想探索该解决方案,可以阅读有关form events

的信息

答案 1 :(得分:1)

<?php

class User
{
    public function setPassword($password)
    {
        if (false == empty($password)) {
            $this->password = $password;
        }
    }
}

如果用户的密码不为空,则只会更新密码。

答案 2 :(得分:1)

我认为你应该重新考虑这是否是一个很好的用例。用户是否应该能够编辑其他用户密码?在我们的机构,我们甚至不允许最高级别的管理员执行此任务。

如果用户需要更改密码,我们让他们自己处理。如果他们忘记了密码,我们允许他们通过电子邮件检索密码。如果他们需要帮助调整他们的电子邮件,我们允许我们的管理员协助用户。但所有密码更新和创建都是由用户完成的。

我觉得FOSUserBundle很难做到这一点很好,但如果你必须DonCallisto似乎有一个很好的解决方案。

答案 3 :(得分:0)

我找到了一个简单的黑客来摆脱“输入密码”表单错误。 Manualy在用户实体中设置虚拟plainPassword。在表单验证之后,只需在刷新实体之前重置它。

$image_string = (string)$image