首页 > 解决方案 > Symfony 5 使用验证来验证新实体

问题描述

我正在使用 Symfony 5.3.7,并使用 @Assert 注释,尝试在注册时验证新用户。试图理解文档但没有得到任何地方。理想情况下,我希望能够了解如何使用这些注释来验证实体。我尝试过使用一个单独的类,但无法理解,尽管我确实想走这条路,以防我在其他地方重用该组件。(我宁愿不在表格中验证,但如果必须的话,我可以)实体


class User implements UserInterface
{
    use TimestampableEntity;

    /**
     * @var int
     *
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\Column(name="intUserId", type="integer", nullable=false)
     */
    private int $id;

    /**
     * @var string
     *
     * @ORM\Column(name="strFirstName", type="string", nullable=false)
     *
     * @Assert\NotBlank
     * @Assert\Length(
     *        min = 2,
     *        max = 50,
     *        minMessage = "Your first name must be at least {{ limit}} characters long",
     *        maxMessage = "Your first name cannot be longer than {{ limit }} characters"
     * )
     */
    private string $firstName;

    /**
     * @var string
     *
     * @ORM\Column(name="strLastName", type="string", nullable=false)
     *
     * @Assert\NotBlank
     * @Assert\Length(
     *        min = 2,
     *        max = 50,
     *        minMessage = "Your first name must be at least {{ limit}} characters long",
     *        maxMessage = "Your first name cannot be longer than {{ limit }} characters"
     * )
     */
    private string $lastName;

    /**
     * @var string
     *
     * @ORM\Column(name="strUsername", type="string", nullable=false)
     *
     * @Assert\Unique()
     * @Assert\Length(
     *        min = 2,
     *        max = 15,
     *        minMessage = "Your first name must be at least {{ limit}} characters long",
     *        maxMessage = "Your first name cannot be longer than {{ limit }} characters"
     * )
     */
    private string $username;

    /**
     * @var string
     *
     * @ORM\Column(name="strPassword", type="string", nullable=false)
     *
     * @Assert\NotNull()
     * @Assert\Regex(pattern = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$")
     *
     * @SecurityAssert\UserPassword(message = "Password is incorrect, please try again")
     */
    private string $password;

    /**
     * @var string
     *
     * @ORM\Column(name="strEmail", type="string", nullable=false)
     *
     * @Assert\Unique()
     * @Assert\Regex(pattern = "\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b")
     */
    private string $email;

    /**
     * @var boolean
     * 
     *  @ORM\Column(name="bolAcceptTermsConditions", type="bool", nullable=false)
     * 
     * @Assert\NotNull()
     */
    private bool $acceptTermsAndConditions;

    /**
     * @var boolean
     * 
     *  @ORM\Column(name="bolAcceptPrivacyPolicy", type="bool", nullable=false)
     * 
     * @Assert\NotNull()
     */
    private bool $acceptPrivacyPolicy;

    /**
     * @var boolean
     * 
     * @ORM\Column(name="bolEmailOptIn", type="bool", nullable=false)
     * 
     * @Assert\NotNull()
     */
    private bool $emailOptIn;

    /**
     * User constructor.
     *
     * @param string $firstName
     * @param string $lastName
     * @param string $username
     * @param string $email
     * @param string $password
     */
    public function __construct(
        string $firstName,
        string $lastName,
        string $username,
        string $email,
        string $password,
        bool $acceptTermsAndConditions = false,
        bool $acceptPrivacyPolicy = false,
        bool $emailOptIn = false
    ) {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
        $this->username = $username;
        $this->email = $email;
        $this->password = $password;
        $this->acceptTermsAndConditions = $acceptTermsAndConditions;
        $this->acceptPrivacyPolicy = $acceptPrivacyPolicy;
        $this->emailOptIn = $emailOptIn;

        $this->dtmAdded = Carbon::now();
    }

理想情况下,我会传入新实体或数组,在验证器或类似控制器中创建实体

public function register(Request $request): Response
    {
        $registrationForm = $this->createForm(RegistrationFormType::class);

        $registrationForm->handleRequest($request);
        if ($registrationForm->isSubmitted() && $registrationForm->isValid()) {
            
            
            $newUserData = $registrationForm->getData();
            $user = new User(
                $newUserData['firstName'],
                $newUserData['lastName'],
                $newUserData['email'],
                $newUserData['username'],
                $newUserData['password'],
                $newUserData['termsConditions'],
                $newUserData['privacyPolicy'],
                $newUserData['emailFrequency']
            );        

            return new RedirectResponse($request->headers->get('referer'));
        }

        return new RedirectResponse($request->headers->get('referer'));
    }

形式

<?php

declare(strict_types=1);

namespace App\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
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\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class RegistrationFormType extends AbstractType
{
    public const FORM_NAME = 'registrationForm';

    /**
     * Form Builder for Registration Form
     *
     * @param FormBuilderInterface $builder
     * @param array $options
     *
     * @return void
     */
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder->add('firstName', TextType::class, [
            'label' => 'Firstname:',
            'required' => true,
            'attr' => [
                'class' => 'form-input input-type-text',
                'placeholder' => 'John',
            ],

        ]);

        $builder->add('lastName', TextType::class, [
            'label' => 'Lastname:',
            'required' => true,
            'attr' => [
                'class' => 'form-input input-type-text',
                'placeholder' => 'Doe'
            ],

        ]);

        $builder->add('email', EmailType::class, [
            'label' => 'Email:',
            'required' => true,
            'attr' => [
                'class' => 'form-input input-type-email',
                'placeholder' => 'example@example.com'
            ]
        ]);

        $builder->add('username', TextType::class, [
            'label' => 'Username:',
            'required' => true,
            'attr' => [
                'class' => 'form-input input-type-text',
            ]
        ]);

        $builder->add('password', PasswordType::class, [
            'label' => 'Password:',
            'required' => true,
            'attr' => [
                'class' => 'form-input input-type-email',
            ]
        ]);

        $builder->add('termsConditions', CheckboxType::class, [
            'label' => 'I accept the terms & conditions',
            'required' => true,
        ]);

        $builder->add('privacyPolicy', CheckboxType::class, [
            'label' => 'I have read and understood the privacy policy',
            'required' => true,
        ]);

        $builder->add('emailFrequency', ChoiceType::class, [
            'label' => 'Opt in to emails:',
            'multiple' => false,
            'expanded' => true,
            'choices' => [
                'Yes' => true,
                'No' => false,
            ],
        ]);
    }

    /**
     * @param OptionsResolver $resolver
     *
     * @return void
     */
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([]);
    }

    /**
     * @return string
     */
    public function getBlockPrefix(): string
    {
        return self::FORM_NAME;
    }
}

标签: phpsymfonyvalidation

解决方案


所以问题是您没有将新的 User 对象传递给表单,因此在这种情况下不会发生验证。

您可以做些什么来解决这个问题,在这种情况下将表单的 data_class 声明为 User

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

当您在操作中创建表单时,您需要将新的 User 对象传递给它,例如:

$user = new User();
$registrationForm = $this->createForm(RegistrationFormType::class, $user);

您可以删除实例化并将数据发送到用户实体的部分

$user = new User(
            $newUserData['firstName'],
            $newUserData['lastName'],
            $newUserData['email'],
            $newUserData['username'],
            $newUserData['password'],
            $newUserData['termsConditions'],
            $newUserData['privacyPolicy'],
            $newUserData['emailFrequency']
        );

取而代之的是,您应该只使用实体管理器来保存新用户,为此,您需要注入实体管理器,如下所示:

public function register(Request $request, EntityManagerInterface $entityManager): Response

并使用它将用户对象保存到数据库中

if ($registrationForm->isSubmitted() && $registrationForm->isValid()) {
    $entityManager->persist($user);
    $entityManager->flush();
}

推荐阅读