为啥断言跳过验证我的 symfony5 表单用户名字段?

Posted

技术标签:

【中文标题】为啥断言跳过验证我的 symfony5 表单用户名字段?【英文标题】:Why assertion skips to validate my symfony5 form username field?为什么断言跳过验证我的 symfony5 表单用户名字段? 【发布时间】:2021-10-26 10:31:51 【问题描述】:

我的问题涉及用户表单中的一个字段,即用户名。由于断言验证适用于实体中的其他字段,所以我觉得这样做很奇怪 - 跳过断言规则我确实指向 User 实体中的用户名属性并将 null 属性传递给 userFormNewHandler 这会产生错误,尤其是当我发现它不是真的不同于其他领域。我想知道,我错过了什么?

用户类型.php

<?php
namespace App\UserBundle\Form\Type;

use App\UserBundle\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;

class UserType extends AbstractType

    public function buildForm(FormBuilderInterface $builder, array $options)
    
        $builder
            ->add('username', TextType::class, ['required'=>true,
                'invalid_message' => 'Username must not be empty!'])
            ->add('plainPassword', RepeatedType::class, array(
                'type'              => PasswordType::class,
                'mapped'            => false,
                'first_options'     => array('label' => 'New password'),
                'second_options'    => array('label' => 'Confirm new password'),
                'invalid_message' => 'The password fields must match.',
                'required' => true,
                'constraints' => [
                    new NotBlank([
                        'message' => 'Password field must not be blank!'
                    ])]
            ))

            ->add('active_status', ChoiceType::class, [
                'choices'  => [
                    'Active' => true,
                    'Inactive' => false,
                ],])
            ->add('first_name',TextType::class, [
                'required'=>true, 'invalid_message' => 'First name must not be empty!'])
            ->add('last_name', TextType::class, [
                'required'=>true, 'invalid_message' => 'Last name must not be empty!'])
            ->add('email', EmailType::class, [
                'required'=>true, 'invalid_message' => 'Email must not be empty!']);
    

    public function configureOptions(OptionsResolver $resolver)
    
        $resolver->setDefaults([
            'data_class' => User::class,
        ]);
    

这是我的 User.php 实体:

<?php

namespace App\UserBundle\Entity;

use App\UserBundle\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;


/**
 * @ORM\Entity(repositoryClass=UserRepository::class)
 */
class User implements UserInterface, PasswordAuthenticatedUserInterface

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     * @Assert\NotBlank(message="Fill username field")
     */
    private $username;

    /**
     * @ORM\Column(type="json")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @ORM\Column(type="boolean")
     */
    private $active_status;

    /**
     * @ORM\Column(type="string", length=30)
     * @Assert\NotBlank(message="Fill first name field")
     */
    private $first_name;

    /**
     * @ORM\Column(type="string", length=30)
     * @Assert\NotBlank(message="Fill last name field")
     */
    private $last_name;

    /**
     * @ORM\Column(type="string", length=40)
     * @Assert\NotBlank(message="Fill email field")
     */
    private $email;

    /**
     * Representation of account status
     */
    public function getActiveStatus(): bool
    
        return $this->active_status;
    

    /**
     * Setting account status
     */
    public function setActiveStatus(bool $active_status): self
    
        $this->active_status = $active_status;

        return $this;
    
        /**
 * Representation of username
 */
public function getUsername(): string

    return (string) $this->username;


/**
 * Setting username for user
 */
public function setUsername(string $username): self

    $this->username = $username;

    return $this;


    //...

还有 _form.html.twig,表单被渲染的地方:

 form_start(form,  attr: novalidate: 'novalidate' ) 
     form_widget(form) 
    <button class="btn" > button_label|default('Save') </button>
 form_end(form) 

【问题讨论】:

【参考方案1】:

我找到了!那是因为我确实在 setter Username 的方法中指出要严格查找字符串,我猜这阻止了我将 null 属性传递给表单。现在 PHP 验证可以正常工作了 :)

零件生成错误:

用户.php

/**
 * Setting username for user
 */
public function setUsername(string $username): self

    $this->username = $username;

    return $this;

修复:

/**
 * Setting username for user
 */
public function setUsername($username): self

    $this->username = $username;

    return $this;

【讨论】:

以上是关于为啥断言跳过验证我的 symfony5 表单用户名字段?的主要内容,如果未能解决你的问题,请参考以下文章

Symfony 5 登录表单操作返回无效的 CSRF 令牌

在 Symfony 5 中验证 AJAX 提交的表单

为啥我的 Django 表单没有引发验证错误?

在没有浏览器的情况下对WSO2 Identity Server进行身份验证,并获取SAML2断言消息

在 Symfony5.3 上自定义新的身份验证错误消息

Laravel 表单验证,为啥我的视图中没有可用的 $errors 变量?