代码之家  ›  专栏  ›  技术社区  ›  Oscar Manuel Gómez Senovilla

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

  •  0
  • Oscar Manuel Gómez Senovilla  · 技术社区  · 6 年前

    我继承了一个应用程序,我还不是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属性,$planpassword保存表单中输入的文本,以及通常的$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;
    }
    

    /**
     * @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_映射来链接属性和函数,但结果是相同的(即,未显示)。

    我甚至试过构建一个自定义验证器。在所有这些情况下,验证密码时的行为都是正常的,但当密码无效时,表单不会提交,但根本不会出现错误消息(与@UniqueConstraint中定义的其他字段不同)。所以,我要么取消,要么只输入一个有效的密码并提交表单,但是用户没有关于错误的引用(profiler或dev日志也没有显示任何关于这个的信息,所以我必须通过更改密码来解决这个问题)。

    提前谢谢。

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

    // 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 回复  |  直到 6 年前
        1
  •  0
  •   Marcos Regis    6 年前

    回答

    你的代码快完成了。你的问题是你在用

    'error_bubbling' => true
    

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

    在做了一些测试之后,我想有点混淆了表单错误 以及表单域错误。

    表单错误(表单) 表格(表格) ,全部 表单.vars.errors 不会显示。

    子窗体字段 error_bubbling=真

    // 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 检查细枝中窗体视图变量的错误