本文目录导读:

我来详细介绍Symfony框架中的表单系统与主题定制。
Symfony表单基础
创建表单
// src/Form/ProductType.php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, [
'label' => '产品名称',
'attr' => ['class' => 'form-control']
])
->add('price', NumberType::class, [
'label' => '价格',
'attr' => ['class' => 'form-control']
])
->add('save', SubmitType::class, [
'label' => '保存',
'attr' => ['class' => 'btn btn-primary']
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Product::class,
]);
}
}
控制器中使用
// src/Controller/ProductController.php
namespace App\Controller;
use App\Entity\Product;
use App\Form\ProductType;
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 ProductController extends AbstractController
{
#[Route('/product/new', name: 'product_new')]
public function new(Request $request, EntityManagerInterface $entityManager): Response
{
$product = new Product();
$form = $this->createForm(ProductType::class, $product);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($product);
$entityManager->flush();
return $this->redirectToRoute('product_success');
}
return $this->render('product/new.html.twig', [
'form' => $form->createView(),
]);
}
}
表单主题定制
全局主题配置
# config/packages/twig.yaml
twig:
form_themes:
- 'bootstrap_5_layout.html.twig' # Bootstrap 5主题
- 'tailwind_2_layout.html.twig' # Tailwind CSS主题
- 'form/my_custom_theme.html.twig' # 自定义主题
- 'foundation_5_layout.html.twig' # Foundation CSS主题
内置主题选项
# config/packages/framework.yaml
framework:
form:
legacy_error_messages: false
csrf_protection: true
自定义主题模板
{# templates/form/my_custom_theme.html.twig #}
{% block form_row %}
<div class="custom-form-group">
{{ form_label(form) }}
{{ form_widget(form) }}
{{ form_errors(form) }}
</div>
{% endblock %}
{% block form_label %}
{% if label is not same as(false) %}
<label class="custom-label">
{{ label }}
{% if required %}
<span class="required">*</span>
{% endif %}
</label>
{% endif %}
{% endblock %}
{% block form_errors %}
{% if errors|length > 0 %}
<div class="custom-error">
<ul>
{% for error in errors %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endblock %}
每个表单单独使用主题
// 控制器中
$form = $this->createForm(ProductType::class, $product, [
'theme' => 'form/special_theme.html.twig'
]);
{# 模板中指定主题 #}
{% form_theme form 'form/special_theme.html.twig' %}
{# 或多个主题 #}
{% form_theme form with ['form/theme1.html.twig', 'form/theme2.html.twig'] %}
字段级别主题覆盖
{# 为特定字段自定义 #}
{% block _product_name_widget %}
<div class="input-group">
<span class="input-group-text">📦</span>
{{ parent() }}
</div>
{% endblock %}
{% block _product_price_row %}
<div class="price-field">
{{ form_label(form) }}
<div class="input-group">
<span class="input-group-text">¥</span>
{{ form_widget(form) }}
</div>
{{ form_errors(form) }}
</div>
{% endblock %}
常用表单主题示例
Bootstrap 5 主题
{# templates/product/form.html.twig #}
{% form_theme form 'bootstrap_5_layout.html.twig' %}
{{ form_start(form) }}
<div class="row">
<div class="col-md-6">
{{ form_row(form.name) }}
</div>
<div class="col-md-6">
{{ form_row(form.price) }}
</div>
</div>
<div class="row mt-3">
<div class="col-12">
{{ form_row(form.description) }}
</div>
</div>
<div class="row mt-4">
<div class="col-12">
{{ form_row(form.save, {
'attr': {'class': 'btn btn-success'}
}) }}
</div>
</div>
{{ form_end(form) }}
Tailwind CSS 主题
{# templates/product/tailwind_form.html.twig #}
{% form_theme form 'tailwind_2_layout.html.twig' %}
{{ form_start(form, {'attr': {'class': 'space-y-6'}}) }}
<div class="grid grid-cols-1 gap-6">
<div>
{{ form_label(form.name, null, {
'label_attr': {'class': 'block text-sm font-medium text-gray-700'}
}) }}
{{ form_widget(form.name, {
'attr': {
'class': 'mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500'
}
}) }}
{{ form_errors(form.name) }}
</div>
<div>
{{ form_label(form.price, null, {
'label_attr': {'class': 'block text-sm font-medium text-gray-700'}
}) }}
{{ form_widget(form.price, {
'attr': {
'class': 'mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500'
}
}) }}
{{ form_errors(form.price) }}
</div>
</div>
<div class="flex justify-end">
{{ form_widget(form.save, {
'attr': {
'class': 'ml-3 inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500'
}
}) }}
</div>
{{ form_end(form) }}
自定义字段渲染
{# templates/form/custom_fields.html.twig #}
{% block text_widget %}
<div class="custom-text-input">
<input type="text"
{{ block('widget_attributes') }}
value="{{ value }}"
class="form-input {{ errors|length > 0 ? 'is-invalid' : '' }}"
/>
{% if help %}
<small class="form-text text-muted">{{ help }}</small>
{% endif %}
</div>
{% endblock %}
{% block choice_widget_collapsed %}
<div class="custom-select-wrapper">
<select {{ block('widget_attributes') }}
class="form-select {{ errors|length > 0 ? 'is-invalid' : '' }}">
{% if placeholder is not none %}
<option value="" {{ value is empty ? 'selected' : '' }}>
{{ placeholder }}
</option>
{% endif %}
{% for choice in choices %}
<option value="{{ choice.value }}"
{{ choice.value == value ? 'selected' : '' }}>
{{ choice.label }}
</option>
{% endfor %}
</select>
</div>
{% endblock %}
表单帮助文本和验证
{# 在表单类型中添加帮助文本 #}
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('email', EmailType::class, [
'label' => '电子邮箱',
'help' => '请输入有效的邮箱地址',
'attr' => [
'placeholder' => 'example@domain.com',
'class' => 'form-control'
]
])
->add('password', RepeatedType::class, [
'type' => PasswordType::class,
'invalid_message' => '两次输入的密码不一致',
'options' => ['attr' => ['class' => 'form-control']],
'required' => true,
'first_options' => ['label' => '密码'],
'second_options' => ['label' => '确认密码'],
]);
}
表单事件和动态修改
// 表单类型中添加事件监听
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$product = $event->getData();
$form = $event->getForm();
// 根据产品类型动态添加字段
if ($product && $product->getType() === '电子') {
$form->add('warranty', IntegerType::class, [
'label' => '保修期(月)'
]);
}
});
}
最佳实践
主题模板组织
templates/
├── form/
│ ├── themes/
│ │ ├── bootstrap_5_custom.html.twig
│ │ ├── tailwind_custom.html.twig
│ │ └── admin_theme.html.twig
│ ├── fields/
│ │ ├── custom_text.html.twig
│ │ └── custom_select.html.twig
│ └── layout.html.twig
└── product/
└── form.html.twig
性能优化
# config/packages/twig.yaml
twig:
form_themes: ['bootstrap_5_layout.html.twig']
cache: '%kernel.cache_dir%/twig' # 启用Twig缓存
表单主题继承
{# 继承内置主题并扩展 #}
{% extends 'bootstrap_5_layout.html.twig' %}
{% block form_row %}
<div class="mb-3 custom-row">
{{ form_label(form) }}
<div class="input-wrapper">
{{ form_widget(form) }}
{{ form_errors(form) }}
</div>
</div>
{% endblock %}
这些方法可以帮助你创建美观、一致的表单界面,同时保持代码的可维护性,选择合适的主题系统可以显著提升开发效率和用户体验。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播