我正在使用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());
有没有优雅的方法来处理这个用例?
答案 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