本文目录导读:

我来详细介绍Symfony表单系统及其扩展机制。
Symfony Form 基础
创建表单类
// src/Form/UserType.php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('username', TextType::class, [
'label' => '用户名',
'attr' => ['class' => 'form-control'],
'required' => true,
])
->add('email', EmailType::class, [
'label' => '邮箱',
'attr' => ['placeholder' => '请输入邮箱'],
])
->add('save', SubmitType::class, [
'label' => '保存',
'attr' => ['class' => 'btn btn-primary']
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
'csrf_protection' => true,
'csrf_field_name' => '_token',
'csrf_token_id' => 'user_item',
]);
}
}
控制器中使用
// src/Controller/UserController.php
use App\Form\UserType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
class UserController extends AbstractController
{
public function create(Request $request)
{
$user = new User();
$form = $this->createForm(UserType::class, $user, [
'action' => $this->generateUrl('user_create'),
'method' => 'POST',
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// 处理表单数据
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('user_success');
}
return $this->render('user/create.html.twig', [
'form' => $form->createView(),
]);
}
}
表单扩展机制
创建自定义表单扩展
// src/Form/Extension/HelpFormExtension.php
namespace App\Form\Extension;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
class HelpFormExtension extends AbstractTypeExtension
{
public static function getExtendedTypes(): iterable
{
return [FormType::class];
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'help' => null,
]);
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
if ($options['help']) {
$view->vars['help'] = $options['help'];
}
}
}
注册扩展为服务
# config/services.yaml
services:
App\Form\Extension\HelpFormExtension:
tags:
- { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
高级表单扩展示例
文件上传扩展
// src/Form/Extension/FileUploadExtension.php
namespace App\Form\Extension;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\File;
class FileUploadExtension extends AbstractTypeExtension
{
public static function getExtendedTypes(): iterable
{
return [FileType::class];
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'max_size' => '2M',
'allowed_mime_types' => ['image/jpeg', 'image/png'],
]);
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($options) {
$data = $event->getData();
if ($data) {
$constraints = [
new File([
'maxSize' => $options['max_size'],
'mimeTypes' => $options['allowed_mime_types'],
])
];
$event->getForm()->add('file', FileType::class, [
'constraints' => $constraints
]);
}
});
}
}
动态下拉列表扩展
// src/Form/Extension/DynamicChoiceExtension.php
namespace App\Form\Extension;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class DynamicChoiceExtension extends AbstractTypeExtension
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public static function getExtendedTypes(): iterable
{
return [ChoiceType::class];
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'entity_class' => null,
'entity_property' => 'name',
]);
$resolver->setNormalizer('choices', function ($options, $value) {
if ($options['entity_class']) {
$repository = $this->entityManager
->getRepository($options['entity_class']);
$entities = $repository->findAll();
$choices = [];
foreach ($entities as $entity) {
$getter = 'get' . ucfirst($options['entity_property']);
$choices[(string) $entity->$getter()] = $entity->getId();
}
return $choices;
}
return $value;
});
}
}
表单主题扩展
自定义表单主题
{# templates/form/custom_theme.html.twig #}
{% block form_row %}
<div class="form-group{% if errors|length > 0 %} has-error{% endif %}">
{{ form_label(form) }}
{{ form_widget(form, {'attr': {'class': 'form-control'}}) }}
{{ form_errors(form) }}
{% if help is defined %}
<small class="form-text text-muted">{{ help }}</small>
{% endif %}
</div>
{% endblock %}
{% block _user_username_widget %}
<div class="input-group">
<span class="input-group-addon">
<i class="fa fa-user"></i>
</span>
{{ block('form_widget_simple') }}
</div>
{% endblock %}
应用自定义主题
# config/packages/twig.yaml
twig:
form_themes:
- 'form/custom_theme.html.twig'
或者在控制器中指定:
// 在控制器中
$form = $this->createForm(UserType::class, $user, [
'theme' => 'form/custom_theme.html.twig'
]);
表单事件扩展
监听表单事件
// src/Form/EventListener/UserFormListener.php
namespace App\Form\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class UserFormListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
FormEvents::PRE_SET_DATA => 'onPreSetData',
FormEvents::POST_SUBMIT => 'onPostSubmit',
FormEvents::SUBMIT => 'onSubmit',
];
}
public function onPreSetData(FormEvent $event)
{
$user = $event->getData();
$form = $event->getForm();
if ($user && $user->getId()) {
// 编辑模式:添加额外字段
$form->add('updatedAt', DateType::class, [
'widget' => 'single_text',
'disabled' => true,
]);
} else {
// 新建模式:添加密码字段
$form->add('password', PasswordType::class);
}
}
public function onPostSubmit(FormEvent $event)
{
$user = $event->getData();
if ($user && $user->getEmail()) {
$user->setEmail(strtolower($user->getEmail()));
}
}
public function onSubmit(FormEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
// 验证逻辑
if ($data['password'] !== $data['confirmPassword']) {
$form->get('confirmPassword')->addError(
new FormError('密码不匹配')
);
}
}
}
在表单类中使用
// src/Form/UserType.php
use App\Form\EventListener\UserFormListener;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventSubscriber(new UserFormListener());
// ... 其他字段
}
}
最佳实践
表单类型扩展注册
# config/services.yaml
services:
# 注册表单类型扩展
form.type_extension.form:
class: App\Form\Extension\HelpFormExtension
tags:
- { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
# 注册表单类型
App\Form\CustomType:
tags: ['form.type']
# 注册表单事件监听器
App\Form\EventListener\UserFormListener:
tags:
- { name: kernel.event_listener, event: form.post_submit, method: onPostSubmit }
表单验证分组
class UserType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'validation_groups' => function (FormInterface $form) {
$data = $form->getData();
if ($data && $data->getId()) {
return ['Default', 'update'];
}
return ['Default', 'create'];
},
]);
}
}
表单数据转换器
// src/Form/DataTransformer/DateTimeToTimestampTransformer.php
namespace App\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
class DateTimeToTimestampTransformer implements DataTransformerInterface
{
public function transform($value)
{
if ($value instanceof \DateTime) {
return $value->getTimestamp();
}
return null;
}
public function reverseTransform($value)
{
if ($value) {
return (new \DateTime())->setTimestamp($value);
}
return null;
}
}
这些扩展机制让Symfony表单系统变得非常灵活和强大,可以根据项目需求进行各种定制和扩展。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播