使用自定义验证方法时表单中的symfony错误消息

时间:2018-08-13 23:46:26

标签: forms symfony validation callback

我继承了一个应用程序,但我还不是Symfony专家。该应用程序具有一个简单的用户实体(当然还有其他一些功能),并且具有一些独特的约束条件:

/**
 * User
 *
 * @ORM\Table(name="users")
 * @ORM\Entity
 * @UniqueEntity(
 *     fields={"username", "school"},
 *     message="There's already a registered user with that login in this school."
 * )
 * @UniqueEntity(fields={"email"},
 *      message="That email is already registered")
 * )
 */

在创建表单时,以及违反此类约束时,消息将显示在表单本身上,并且流程不会返回到控制器(完全可以)。

我有一个非ORM属性,带有$ plainPassword,它以表格形式保存输入的文本,以及通常的$ password保持加密的密码。这是此字段的表单部分:

    $builder->add(
        'plainPassword',
        TextType::class,
        [
            'required' => false,
            'attr' =>
            [
                'autocomplete' => 'off',
            ],
            'error_bubbling' => true,
        ]
    )
    ;

现在,对于密码,我有一个自定义验证器,可以在下一个功能中看到它:

public function isPasswordValid(string $p = null)
{
    if (null==$p) {
        $p = $this->getPlainPassword();
    }

    // If I'm not changing the password, there must be one previously
    $success = strlen($this->getPassword())>0;
    if (strlen($p)) {
        $success = (strlen($p)>7 && preg_match('/[A-Za-z]/', $p) && preg_match('/[0-9]/', $p));
    }
    return $success;
}

此函数本身可以很好地工作,但是我想将其附加到表单,以便当plainPassword字段具有“无效”密码(即该函数返回false)时。因此,我尝试在函数之前使用注释块:

/**
 * @Assert\IsTrue(message = "The password is not a valid password")
 */
public function isPasswordValid(string $p = null)
{
    if (null==$p) {
        $p = $this->getPlainPassword();
    }

    // If I'm not changing the password, there must be one previously
    $success = strlen($this->getPassword())>0;
    if (strlen($p)) {
        $success = (strlen($p)>7 && preg_match('/[A-Za-z]/', $p) && preg_match('/[0-9]/', $p));
    }
    return $success;
}

消息进入form.errors,当以非特定方式(但不同)在非模式模式下调用表单时,我可以显示该消息,但是通过ajax的默认表单行为显示为弹出窗口甚至跳过这种行为,所以我没有收到此消息。然后,我尝试在表单的字段定义中使用error_mapping来链接属性和函数,但是结果是相同的(即,未显示)。

我什至尝试构建自定义验证器。在所有这些情况下,验证密码时的行为都可以,但是当密码无效时,不提交表单,但根本没有错误消息(与@UniqueConstraint中定义的其他字段不同)。因此,我取消了或者只是输入了一个有效的密码并提交了表单,但是用户没有关于错误的引用(并且探查器或开发日志没有显示任何有关此的内容,因此我必须弄清楚通过更改密码)。

因此,肯定有我缺少的东西,或者仅仅是通过我测试的手段是不可能的。我现在正在使用表达式语言来寻找表达式断言,但是我已经耗尽了想法,为此花了我几天的时间,因此在这一点上我需要您的帮助,以找出我做错了什么,被忽略或尚未这么做。

谢谢。

更新:添加了一个自定义验证器,在该验证器中,我不确定是否正确管理了空数据或任何相关内容。

// ValidPassword.php
namespace XXX\UsersBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class ValidPassword extends Constraint
{
    public $message = 'InvalidPasswordMessage';
}

(我希望消息由翻译文件处理。)

// ValidPasswordValidator.php
namespace XXX\UsersBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use XXX\UsersBundle\Entity\User;

class ValidPasswordValidator extends ConstraintValidator
{
    public function validate($p, Constraint $constraint)
    {

        $success = true;
        if (strlen($p)) {
            $success = (strlen($p)>7 && preg_match('/[A-Za-z]/', $p) && preg_match('/[0-9]/', $p));
        }

        if (!$success) {
            $this->context->buildViolation($constraint->message)
                ->addViolation();

        }
    }

在实体中:

use XXX\UsersBundle\Validator\Constraints as UserAssert;
...

    /**
     * @var string
     * @UserAssert\ValidPassword
     */
    private $plainPassword;

这是树枝模板的一部分,用于显示涉及的字段:

...

<div class="row">
    <div class="col-md-4">
    {{ form_row(form.name) }}
    </div>
    <div class="col-md-4">
    {{ form_row(form.surname) }}
    </div>
</div>

<div class="row">
    <div class="col-md-4">
{{ form_row(form.email) }}
    </div>
</div>

<div class="row">
    <div class="col-md-4">
{{ form_row(form.plainPassword) }}
    </div>
</div>

1 个答案:

答案 0 :(得分:0)

回答

您的代码几乎完成了。您的麻烦是您正在使用

'error_bubbling' => true

此配置将错误对象更改为附加到父字段目标或表单的对象。因此,在您的情况下,plainPasswordField中的错误将添加到表单而不是字段中。

更多信息

进行了一些测试之后,我想关于Form Errors会有些混乱 和表单字段错误。

如果您的视图代码没有 form_errors(form) form(form),则所有 form.vars.errors 都不会显示出来。

具有 error_bubbling = true 或类似代码的子表单字段:

// Generic Controller
$form->addError(new FormError('My Generic Form Error not associate with any field!'));
return $this->render('my_template.html.twig', [
        'form' => $form->createView(),
    ]);

olny可以显示在树枝模板中,

form_errors(form)
  

有用的提示:

  • 在创建表单模板时,请使用form(form)(必须是模板的第一个调用)调试表单视图,以显示表单对象中的所有内容,例如字段(使用html表单输入| select, 字段标签,字段错误,字段助手)和表单本身中的错误 该文档说了form_rest(),但未显示form.vars.errors

  • 使用form.vars.errors|length检查树枝中表单视图变量上的错误