我尝试在表单中使用特定的验证器。
这个表单是让用户重新定义他的密码,他还必须输入他当前的密码。
在我的表单中:
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
表单类型如下所示:
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('currentpassword', 'password', array('label'=>'Current password',
'mapped' => false,
'constraints' => new UserPassword(array('message' => 'you wot m8?')),
'required' => true
))
->add('password', 'repeated', array(
'first_name' => 'new',
'second_name' => 'confirm',
'type' => 'password',
'required' => true
))
;
}
我知道在我的控制器中,我可以只获得数据表单,获得currentpassword值,调用security.encoder_factory等,但是那个验证器看起来很方便。
我的问题是表单总是返回一个错误(这里是:“你知道m8吗?”)就像我输入了错误的当前密码一样。
知道我做错了什么吗?
3条答案
按热度按时间oymdgrw71#
我知道这个答案晚了几年,但当我在同一个问题上遇到困难时,我想提出我的解决方案:
问题是,在我的例子中,在用于FormMapping的
$user
实体和来自security.context
的User
之间有一个连接。请参见以下内容:(密码更改-控制器)
isValid()
函数正在触发UserPassword约束验证器:感兴趣的行是:
if (!$encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt()))
在我的例子中,
$user->getPassword()
返回了我刚刚在表单中输入的新密码作为我的新密码。**这就是为什么测试总是失败!**我不明白为什么tokenStorage中的用户和我从数据库加载的用户之间会有连接。感觉就像两个对象(MyDatabase一和tokenStorage一)共享相同的处理器地址,并且实际上是相同的...奇怪!
我的解决方案是将ChangePasswordType中的(新)密码字段与EntityMapping分离:请参阅
感兴趣的行为
'mapped' => false,
这样,在表单中输入的新密码将不会自动Map到给定的
$user
实体。相反,您现在需要从form
获取它。请参见这是一个解决我不能完全理解的问题的方法。如果有人能解释一下数据库对象和security.context对象之间的联系,我很高兴听到!
iyr7buue2#
我遇到了同样的问题,经过大量的研究和实际测试,这是我使用的解决方案:
1.保持用户实体不变(无更改)
(NB:如果你不把这个实体定义为模型,那么你就不能Map它,以后在表单中,除非你创建它抛出Doctrine,而这不是我们的目的)
我希望这能帮助到一些人...
rsl1atfo3#
我发现自己在
UserPassword
上也浪费了时间,我想为那些想要“更改密码表单”的人分享一个更简单的解决方案。其他答案已经解释了使用UserPassword时会出现什么错误,但与其添加额外的实体或在控制器中瞎折腾,不如使用一种更直接的方法来添加您自己的检查,并在无效时添加表单错误:
这应该可以让您的控制器不需要额外的检查(
$form->isValid()
是所有需要调用的)