Symfony 5注册表格验证不起作用

如何解决Symfony 5注册表格验证不起作用

我是第一次学习Symfony。

Form Validation不能按预期工作,按照Symfony文档,我确实留下了样板代码,我阅读了10次其他堆栈溢出文章和文档,以查看是否错过了某些内容,但我无法弄清楚出来。

客户端验证已关闭,基本上可以正常测试服务器端验证。 但是,提交表单后,即使表单为空且数据无效,isValid()方法也将返回true。我在Entity和formType中都添加了约束,但是它绕过了一切,我知道这是事实,因为异常是由数据库或密码编码方法抛出的。

我下面有一个简单的代码示例,请检查:

ps:这是一个用于学习的虚拟项目, 这是代码:

//App\Entity\MyFavorite.php

//App\Controller\RegistrationController:

<?php

namespace App\Controller;
use App\Entity\MyFavorite;
use App\Form\RegistrationFormType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

use Symfony\Component\Security\Core\
Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class RegistrationController extends AbstractController
{
    /**
    * @Route("/register",name="app_register")
    */
    public function register(
        Request $request,UserPasswordEncoderInterface $passwordEncoder,ValidatorInterface $validator): Response
    {
        $user = new MyFavorite();
        $form = $this->createForm(
             RegistrationFormType::class,$user
        );
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {

        // encode the plain password
        $user->setPassword(
            $passwordEncoder->encodePassword(
                $user,$form->get('plainPassword')->getData()
            )
        );

        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($user);
        $entityManager->flush();
        // do anything else you need here,like send an email

        return $this->redirectToRoute('myfav_vault');
    }

    return $this->render('registration/register.html.twig',[
        'registrationForm' => $form->createView()
        ]);
    }
}


//App\Entity\MyFavorite
<?php

    namespace App\Entity;

    use App\Repository\MyFavoriteRepository;
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    use Symfony\Component\Security\Core\User\UserInterface;

    //-> Bringing in the Validator Constraints as Assert
    use Symfony\Component\Validator\Constraints as Assert;

    /**
     * @ORM\Entity(repositoryClass=MyFavoriteRepository::class)
     * @UniqueEntity(fields={"uniqueCode"},message="There is already an   account with this uniqueCode")
     */
    class MyFavorite implements UserInterface
    {
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string",length=11,unique=true)
     * -> Adding my first custom assertion:
     * @Assert\Regex("/^[a-zA-Z0-9]{3}-[a-zA-Z0-9]{3}-[a-zA-Z0-9]. {3}$/")
     * @Assert\Length(
     *    min = 11,*    max = 11
     * )
     */
    private $uniqueCode;

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

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

    /**
     * @ORM\Column(type="string",length=100)
     * @Assert\NotBlank
     */
    private $name;


    public function getId(): ?int
    {
        return $this->id;
    }

    public function getUniqueCode(): ?string
    {
        return $this->uniqueCode;
    }

    public function setUniqueCode(string $uniqueCode): self
    {
        $this->uniqueCode = $uniqueCode;

        return $this;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string) $this->uniqueCode;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getPassword(): string
    {
        return (string) $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getSalt()
    {
       //not needed when using the "bcrypt" algorithm insecurity.yaml
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary,sensitive data on the user,// $this->plainPassword = null;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getExpiry(): ?\DateTimeInterface
    {
        return $this->expiry;
    }

    public function setExpiry(?\DateTimeInterface $expiry): self
    {
        $this->expiry = $expiry;

        return $this;
    }
}    


//App\Form\RegistrationFormType
<?php

namespace App\Form;

use App\Entity\MyFavorite;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
//-> Getting basic TextType
use Symfony\Component\Form\Extension\Core\Type\TextType;

use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\IsTrue;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Regex;

//-> Testing out with Regex and String

class RegistrationFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder,array $options)
    {
        $builder
            ->add('name')
            ->add('uniqueCode')
            ->add('plainPassword',PasswordType::class,[
                // instead of being set onto the object directly,// this is read and encoded in the controller
                'mapped' => false,'constraints' => [
                    new NotBlank([
                        'message' => 'Please enter a password',]),//-> I am removing this as I do not want to provide options for min/max length
                    /*new Length([
                        'min' => 6,'minMessage' => 'Your password should be at least {{ limit }} characters',// max length allowed by Symfony for security reasons
                        'max' => 4096,*/
                ],])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => MyFavorite::class,//->Im going to turn of form validation on the client to see if the validation works on the server:
            'validation_groups' => false
        ]);
    }
}


//register.html.twig:




  {% extends 'base.html.twig' %}

{% block title %}Register{% endblock %}

{% block body %}
    {% for flashError in app.flashes('verify_email_error') %}
        <div class="alert alert-danger" role="alert">{{ flashError }}</div>
    {% endfor %}

    <h1>Register</h1>
    
    {{ form_start(registrationForm,{'attr': {'novalidate':'novalidate'}}) }}
        {# This line had to be added manually so the form comes at the right place,some how all fields were not included #}
        {{ form_row(registrationForm.name) }}
        {{ form_row(registrationForm.uniqueCode) }}
        {{ form_row(registrationForm.plainPassword,{
            label: 'Password'
        }) }}
        

        <button type="submit" class="btn">Register</button>
    {{ form_end(registrationForm) }}
{% endblock %}

发现:

提交完全空白的表格时: 当password字段为null且需要字符串时,encodePassword()会引发异常,(它甚至不应进入此阶段,因为我以为isValid()应该返回false?)

使用密码和所有其他密码作为空值提交: 绕过所有内容,只有数据库抛出异常。

为uniqueCode提交了错误的模式:验证器甚至无法识别任何东西,并且每次都会通过

handleRequest()方法不会引发任何异常或返回false,但密码除外,在密码中我遇到一个非常丑陋的错误,说密码的参数2不能为null, 因此很明显,验证没有发生,isValid()返回true。

错误异常来自数据库,

当我尝试以错误的模式插入唯一代码时,它不会被插入, 名称为空时,它将通过验证,但数据库会引发异常, 当密码字段为空时,它仍会通过验证,

Symfony文档说:

handleRequest()方法将数据写回到同一对象,

然后我们验证数据:

“在上一节中,您学习了如何使用有效或无效数据提交表单。在Symfony中,问题不是“表单”是否有效,而是基本对象($ task在此示例)在表单将提交的数据应用于表单之后才有效。调用$ form-> isValid()是询问$ task对象是否具有有效数据的快捷方式。“

我试图查看ValidatorInterface文档,但其中明确指出: “大多数时候,您不会直接与验证程序服务进行交互,也不必担心打印出错误。大多数时候,您将在处理提交的表单数据时间接使用验证。有关更多信息,请参见如何验证Symfony表单。”

我在这里想念什么?

解决方法

这不是Stackoverflow的正确格式,但是我们可以看到关闭之前可以走多远。可能需要在Reddit Symfony论坛上继续。

通过以下操作开始,从小做起。请注意,没有实体或其他东西在进行。只是想让自己相信验证的基础确实有效:

class RegistrationController extends AbstractController
{
    public function register(Request $request)
    {
        $form = $this->createFormBuilder()
            ->add('username',TextType::class,[
                'constraints' => new NotBlank(['message' => 'User name cannot be blank'])
            ])
            ->add('save',SubmitType::class,['label' => 'Register'])
            ->getForm();

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            dump('Validated');
        }
        return $this->render('user/register.html.twig',['form' => $form->createView()]);

    }
}

# user/register.html.twig
{% extends 'base.html.twig' %}

{% block body %}
    <h1>Register Form</h1>
    {{ form_start(form,{'attr':{'novalidate':'novalidate'}}) }}
    {{ form_end(form) }}
{% endblock %}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-