Symfony2 - 如何在CallbackValidator中使用实体变量?

时间:2012-02-14 15:35:49

标签: php symfony

我有一个使用一些自定义验证器构建的表单,它们就像魅力一样,但我在添加一个与其他验证器略有不同的新验证器时遇到了问题。

基本上我需要根据我通常可以从实体中提取的值来检查表单中的数据。

在这种情况下,我需要获取用户密码salt(使用$ user-> getSalt())。问题似乎是CallbackValidator类不能接受除$ form之外的任何其他数据。

我的代码:

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

    $form = $this->createFormBuilder($user)
            ->add('password', 'password')
            ->add('newPassword', 'password', array('label' => 'New Password', 'property_path' => false))
            ->add('confirmPassword', 'password', array('label' => 'Confirm Password', 'property_path' => false))
            ->addValidator(new CallbackValidator(function($form)
            {
                $encoder = new MessageDigestPasswordEncoder('sha1', false, 1);
                $password = $encoder->encodePassword($form['password']->getData(), $user->getSalt());

                if($password != $user->getPassword()) {
                    $form['password']->addError(new FormError('Incorrect password'));
                }
                if($form['confirmPassword']->getData() != $form['newPassword']->getData()) {
                    $form['confirmPassword']->addError(new FormError('Passwords must match.'));
                }
                if($form['newPassword']->getData() == '') {
                    $form['newPassword']->addError(new FormError('Password cannot be blank.'));
                }
            }))
            ->getForm();

现在,这是我得到的错误:

Fatal error: Call to a member function getSalt() on a non-object in /Sites/src/UserBundle/Controller/DashboardController.php on line 57

第57行:

$password = $encoder->encodePassword($form['password']->getData(), $user->getSalt());

我尝试了各种尝试并将盐传递给CallbackValidator,到目前为止,唯一的方法是将其作为hiddne字段添加到表单中但这是不可接受的,因为它存在安全风险,我还需要将散列密码添加为隐藏字段以匹配输入。

必须有一种更简单的方法吗?

1 个答案:

答案 0 :(得分:6)

来自$this->get('security.context')->getToken()->getUser();的$ user变量未在匿名函数范围内定义。

与从父作用域继承的javascript等语言(自动闭包)相反, 你需要明确地要求php来做。 use关键字专门用于:http://php.net/manual/en/functions.anonymous.php

$user = new User;
function($form) use($user) { 

};

这是一个更好的解释:) Javascript closures vs PHP closures, what's the difference?

所以你应该做的就是修改你的代码:

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

$form = $this->createFormBuilder($user)
        ->add('password', 'password')
        ->add('newPassword', 'password', array('label' => 'New Password', 'property_path' => false))
        ->add('confirmPassword', 'password', array('label' => 'Confirm Password', 'property_path' => false))
        ->addValidator(new CallbackValidator(function($form) use($user)
        {
            $encoder = new MessageDigestPasswordEncoder('sha1', false, 1);
            $password = $encoder->encodePassword($form['password']->getData(), $user->getSalt());

            if($password != $user->getPassword()) {
                $form['password']->addError(new FormError('Incorrect password'));
            }
            if($form['confirmPassword']->getData() != $form['newPassword']->getData()) {
                $form['confirmPassword']->addError(new FormError('Passwords must match.'));
            }
            if($form['newPassword']->getData() == '') {
                $form['newPassword']->addError(new FormError('Password cannot be blank.'));
            }
        }))
        ->getForm();