本文目录导读:

我来详细解释 Symfony Form 组件与验证功能的使用方法。
创建表单类
// src/Form/UserType.php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
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\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('username', TextType::class, [
'label' => '用户名',
'attr' => [
'placeholder' => '请输入用户名',
'class' => 'form-control'
]
])
->add('email', EmailType::class, [
'label' => '邮箱',
'attr' => ['placeholder' => '请输入邮箱']
])
->add('password', PasswordType::class, [
'label' => '密码',
'attr' => ['placeholder' => '请输入密码']
])
->add('submit', SubmitType::class, [
'label' => '提交',
'attr' => ['class' => 'btn btn-primary']
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
'validation_groups' => ['Default', 'registration']
]);
}
}
实体类与验证约束
// src/Entity/User.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 50)]
#[Assert\NotBlank(message: '用户名不能为空')]
#[Assert\Length(
min: 3,
max: 50,
minMessage: '用户名至少{{ limit }}个字符',
maxMessage: '用户名最多{{ limit }}个字符'
)]
#[Assert\Regex(
pattern: '/^[a-zA-Z0-9_]+$/',
message: '用户名只能包含字母、数字和下划线'
)]
private ?string $username = null;
#[ORM\Column(length: 180, unique: true)]
#[Assert\NotBlank(message: '邮箱不能为空')]
#[Assert\Email(message: '请输入有效的邮箱地址')]
private ?string $email = null;
#[ORM\Column(length: 255)]
#[Assert\NotBlank(message: '密码不能为空')]
#[Assert\Length(
min: 8,
max: 255,
minMessage: '密码至少{{ limit }}个字符'
)]
#[Assert\Regex(
pattern: '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$/',
message: '密码必须包含大小写字母和数字'
)]
private ?string $password = null;
// Getters and Setters
public function getId(): ?int { return $this->id; }
public function getUsername(): ?string { return $this->username; }
public function setUsername(string $username): self { $this->username = $username; return $this; }
public function getEmail(): ?string { return $this->email; }
public function setEmail(string $email): self { $this->email = $email; return $this; }
public function getPassword(): ?string { return $this->password; }
public function setPassword(string $password): self { $this->password = $password; return $this; }
}
控制器中使用表单
// src/Controller/UserController.php
namespace App\Controller;
use App\Entity\User;
use App\Form\UserType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class UserController extends AbstractController
{
#[Route('/user/new', name: 'user_new')]
public function new(Request $request, EntityManagerInterface $entityManager): Response
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// 验证通过后的处理
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('success', '用户创建成功!');
return $this->redirectToRoute('user_list');
}
return $this->render('user/new.html.twig', [
'form' => $form->createView(),
]);
}
#[Route('/user/{id}/edit', name: 'user_edit')]
public function edit(Request $request, User $user, EntityManagerInterface $entityManager): Response
{
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
$this->addFlash('success', '用户信息已更新!');
return $this->redirectToRoute('user_list');
}
return $this->render('user/edit.html.twig', [
'form' => $form->createView(),
'user' => $user
]);
}
}
自定义验证器
// src/Validator/Constraints/UniqueUser.php
namespace App\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
#[\Attribute]
class UniqueUser extends Constraint
{
public string $message = '该用户名已被使用';
public function validatedBy(): string
{
return static::class.'Validator';
}
}
// src/Validator/Constraints/UniqueUserValidator.php
namespace App\Validator\Constraints;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class UniqueUserValidator extends ConstraintValidator
{
private EntityManagerInterface $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function validate($value, Constraint $constraint): void
{
if (!$constraint instanceof UniqueUser) {
return;
}
$existingUser = $this->entityManager
->getRepository(User::class)
->findOneBy(['username' => $value]);
if ($existingUser) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $value)
->addViolation();
}
}
}
条件验证组
// 在实体中使用验证组
#[ORM\Entity]
class UserRegistration
{
#[Assert\NotBlank(groups: ['registration'])]
#[Assert\Length(min: 3, groups: ['registration'])]
private ?string $username = null;
#[Assert\NotBlank(groups: ['profile'])]
#[Assert\Length(min: 2, groups: ['profile'])]
private ?string $fullName = null;
}
// 在表单中指定验证组
$form = $this->createForm(UserRegistrationType::class, $user, [
'validation_groups' => ['registration', 'Default']
]);
模板中显示表单和错误
{# templates/user/new.html.twig #}
{% extends 'base.html.twig' %}
{% block body %}
<div class="container mt-5">
<h1>创建新用户</h1>
{{ form_start(form, {'attr': {'class': 'needs-validation', 'novalidate': 'novalidate'}}) }}
{% if form_errors(form) %}
<div class="alert alert-danger">
{{ form_errors(form) }}
</div>
{% endif %}
<div class="mb-3">
{{ form_label(form.username, null, {'label_attr': {'class': 'form-label'}}) }}
{{ form_widget(form.username, {'attr': {'class': 'form-control'}}) }}
{% if form_errors(form.username) %}
<div class="invalid-feedback d-block">
{{ form_errors(form.username) }}
</div>
{% endif %}
{{ form_help(form.username) }}
</div>
<div class="mb-3">
{{ form_label(form.email, null, {'label_attr': {'class': 'form-label'}}) }}
{{ form_widget(form.email, {'attr': {'class': 'form-control'}}) }}
{% if form_errors(form.email) %}
<div class="invalid-feedback d-block">
{{ form_errors(form.email) }}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form_label(form.password, null, {'label_attr': {'class': 'form-label'}}) }}
{{ form_widget(form.password, {'attr': {'class': 'form-control'}}) }}
{% if form_errors(form.password) %}
<div class="invalid-feedback d-block">
{{ form_errors(form.password) }}
</div>
{% endif %}
</div>
{{ form_rest(form) }}
<button type="submit" class="btn btn-primary">提交</button>
{{ form_end(form) }}
</div>
{% endblock %}
自定义验证规则
// 使用回调验证
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
#[Assert\Callback]
public function validate(ExecutionContextInterface $context): void
{
if ($this->password === $this->username) {
$context->buildViolation('密码不能与用户名相同')
->atPath('password')
->addViolation();
}
}
表单事件订阅
// 动态修改表单
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (isset($data['userType']) && $data['userType'] === 'admin') {
$form->add('adminCode', TextType::class);
}
});
配置 validation.yaml
# config/packages/validator.yaml
framework:
validation:
enabled: true
email_validation_mode: html5
mapping:
paths:
- '%kernel.project_dir%/config/validator/validation.yaml'
Symfony Form 和 Validation 组件提供了强大的表单处理和数据验证功能,能够满足各种复杂的表单需求。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播