指尖上的记忆指尖上的记忆
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub

最近做项目,需要做表单验证,我用两种方法,分别是 验证器验证和闭包函数验证,代码如下: RegistrationFormType.php:

<?php

namespace App\Form;

use App\Entity\User;
use App\Validator\EmailFormat;
use App\Validator\EmailUnique;
use QINGHONG\CommonBundle\Validator\Constraints\StrongPassword;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Context\ExecutionContext;

class RegistrationFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('email', TextType::class, [
                'constraints' => [
                    new NotBlank([
                        'message' => 'Please enter a email',
                    ]),
                    new EmailFormat([
                        'message' => 'Please enter a normal email',
                    ]),
                    new EmailUnique([
                        'message' => 'Current email already exists!',
                    ])
                ],
            ])
            ->add('password', PasswordType::class, [
                'mapped'      => false,
                'constraints' => [
                    new NotBlank([
                        'message' => 'Please enter a password',
                    ]),
                    new StrongPassword(),
                ],
            ])
            ->add('confirmPassword', PasswordType::class, [
                'mapped'      => false,
                'constraints' => [
                    new Callback(['callback' => function ($value, ExecutionContext $ctx) {
                        if (empty($value)) {
                            $ctx->addViolation("Please enter a confirm password");
                        } elseif ($ctx->getRoot()['password']->getData() !== $value) {//这一行很重要,就是通过ctx 上下文获取数据
                            $ctx->addViolation("The entered passwords do not match");
                        }
                    }]),
                ],
            ])
            ->add('firstName', TextType::class, [
                'constraints' => [
                    new Callback(['callback' => function ($value, ExecutionContext $ctx) use ($builder) {
                        if (preg_match_all("/([\x{4e00}-\x{9fa5}]+)/u", trim($value), $match)) {
                            $ctx->addViolation('Please do not enter chinese characters');
                        }

                        if (strlen(trim($value)) > 30) {
                            $ctx->addViolation("The content should not be more than 30 words");
                        } elseif (strlen(trim($value)) == 0) {
                            $ctx->addViolation('Please enter the firstName');
                        }
                    }]),
                ]
            ])
            ->add('middleName', TextType::class, [
                'constraints' => [
                    new Callback(['callback' => function ($value, ExecutionContext $ctx) use ($builder) {
                        if (strlen(trim($value)) > 0) {
                            if (preg_match_all("/([\x{4e00}-\x{9fa5}]+)/u", trim($value), $match)) {
                                $ctx->addViolation('Please do not enter chinese characters');
                            }

                            if (strlen(trim($value)) > 30) {
                                $ctx->addViolation("The content should not be more than 30 words");
                            }
                        }
                    }]),
                ]
            ])
            ->add('lastName', TextType::class, [
                'constraints' => [
                    new Callback(['callback' => function ($value, ExecutionContext $ctx) use ($builder) {
                        if (preg_match_all("/([\x{4e00}-\x{9fa5}]+)/u", trim($value), $match)) {
                            $ctx->addViolation('Please do not enter chinese characters');
                        }

                        if (strlen(trim($value)) > 30) {
                            $ctx->addViolation("The content should not be more than 30 words");
                        } elseif (strlen(trim($value)) == 0) {
                            $ctx->addViolation('Please enter the lastName');
                        }
                    }]),
                ]
            ]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class'      => User::class,
            // enable/disable CSRF protection for this form
            'csrf_protection' => true,
            // the name of the hidden HTML field that stores the token
            'csrf_field_name' => '_token',
            // an arbitrary string used to generate the value of the token
            // using a different string for each form improves its security
            'csrf_token_id'   => 'user_register',
        ]);
    }
}

接下来准备改为基于 constraints 验证函数的方式

...
...
->add('password', RepeatedType::class, [
                'type'            => PasswordType::class,
                'first_name'      => 'password',
                'second_name'     => 'confirmPassword',
                'invalid_message' => 'The password fields must match', //这里有个问题就是,password 和 confirmPassword 只能公用一个提示信息,不能像上面那样分别提示
                'constraints'     => [
                    new NotBlank([
                        'message' => 'Please enter the password',
                    ]),
                    new StrongPassword(),
                ]
            ])
...
...

只用一个 password 字段表示,通过 first_name 和 second_name 来区分页面展示的字段内容

<div class="form-label-group">
                <label for="password" class="control-label">*</label>
                <input type="password" id="inputPassword" name="registration_form[password][password]" class="form-control inputPassword" placeholder="Password" required="" value="{{ user.password }}">
                {% if errors and errors.password is defined %}
                    <div class="invalid-feedback d-block">{{ errors['password'] }}</div>
                {% else %}
                    <div class="invalid-feedback d-block hold-empty"></div>
                {% endif %}
            </div>
            <div class="form-label-group">
                <label for="confirmPassword" class="control-label">*</label>
                <input type="password" id="inputConfirmPassword" name="registration_form[password][confirmPassword]" class="form-control inputConfirmPassword" placeholder="ConfirmPassword" required="" value="{{ user.password }}">
                {% if errors and errors.password is defined %}
                    <div class="invalid-feedback d-block">{{ errors['password'] }}</div>
                {% else %}
                    <div class="invalid-feedback d-block hold-empty"></div>
                {% endif %}
            </div>