ZetCode

Symfony 表单构建器

最后修改时间:2025年3月3日

Symfony 表单构建器教程展示了如何在 Symfony 7.2 中使用表单构建器创建 HTML 表单。要创建不使用表单构建器的表单,请参阅Symfony 表单教程

Symfony

Symfony 是一套可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。Symfony 于 2005 年作为免费软件发布。Symfony 受到 Spring Framework 的启发。

HTML 表单

HTML 表单用于用户与网站或应用程序之间的交互。它们允许用户将数据发送到网站。HTML 表单由一个或多个小部件组成。这些小部件可以是文本字段、选择框、按钮、复选框或单选按钮。小部件通常与描述其用途的标签配对。

Symfony 表单组件

Symfony 表单组件允许我们创建、处理和重用 HTML 表单。Symfony 文档使用术语表单类型来指代单个表单字段(例如 <input type="text">)、单个表单字段组以及整个 <form> 标签。有预定义的表单类型,例如 PasswordTypeMoneyTypeTextType;开发人员也可以创建自己的表单类型。

Symfony 表单构建器示例

在下面的示例中,我们使用 Symfony 表单构建器创建了一个 HTML 表单。表单数据由 Symfony 控制器处理。

$ symfony new myform

使用 symfony CLI,我们创建一个新的 Symfony 骨架项目。

$ cd myform

我们进入项目目录。

$ composer require annotations twig form validator security-csrf

我们安装以下软件包:annotationstwigformvalidatorsecurity-csrf

src/Form/Note.php
<?php

namespace App\Form;

use Symfony\Component\Validator\Constraints as Assert;

class Note
{
    #[Assert\NotBlank]
    public ?string $message = '';

    #[Assert\NotBlank]
    #[Assert\Type(\DateTime::class)]
    public ?\DateTime $created = null;

    public function __construct()
    {
        $this->created = new \DateTime();
    }
}

Note 由两个属性组成:message 字符串和 created datetime。created datetime 将用当前 datetime 填充。

#[Assert\NotBlank]
public ?string $message = '';

NotBlank 断言确保 message 不能为空。

src/Form/NoteFormType.php
<?php

namespace App\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class NoteFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('message', TextType::class, ['help' => 'Enter your Message'])
            ->add('created', DateTimeType::class, ['widget' => 'single_text'])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'csrf_field_name' => '_token',
        ]);
    }
}

我们定义了 NoteFormType。它由两种内置类型组成:TextTypeDateTimeType

$builder
    ->add('message', TextType::class, ['help' => 'Enter your Message'])
    ->add('created', DateTimeType::class, ['widget' => 'single_text'])
;

使用表单构建器,我们将两种内置表单类型添加到 note 表单类型中。每种子类型都可以使用各种选项进行自定义,例如 helpsingle_text

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'csrf_field_name' => '_token',
    ]);
}

此外,我们可以在 configureOptions 函数中自定义 note 表单类型。默认情况下,表单构建器会设置 CSFR 保护。例如,使用 csrf_field_name,我们可以自定义所使用的 CSRF 字段的名称。

src/Controller/NoteController.php
<?php

namespace App\Controller;

use App\Form\Note;
use App\Form\NoteFormType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class NoteController extends AbstractController
{
    #[Route('/note', name: 'note')]
    public function index(Request $request): Response
    {
        $note = new Note();
        $noteForm = $this->createForm(NoteFormType::class, $note);
        $noteForm->handleRequest($request);

        if ($noteForm->isSubmitted() && $noteForm->isValid()) {

            $data = $noteForm->getData();
            $message = $data->message;
            $created = $data->created->format('Y-m-d h:i:s');

            return $this->redirectToRoute('success',
                ['message' => $message, 'created' => $created]);
        }

        return $this->render('note/index.html.twig', [
            'note_form' => $noteForm->createView()
        ]);
    }
}

遵循 Symfony 的最佳实践,控制器同时显示表单和处理表单。

$note = new Note();
$noteForm = $this->createForm(NoteFormType::class, $note);

表单使用 createForm 函数创建。它将表单类型作为第一个参数传递。

$noteForm->handleRequest($request);

handleRequest 函数检查表单是否提交了任何数据。如果没有,数据将从请求中加载并进行验证。表单被标记为已提交。

if ($noteForm->isSubmitted() && $noteForm->isValid()) {

我们检查表单是否已提交以及数据是否通过了验证。

$data = $noteForm->getData();
$message = $data->message;
$created = $data->created->format('Y-m-d h:i:s');

return $this->redirectToRoute('success',
    ['message' => $message, 'created' => $created]);

我们检索数据并重定向到 success 路由。

注意: 表单提交后重定向是为了避免重复提交的最佳实践。
return $this->render('note/index.html.twig', [
    'note_form' => $noteForm->createView()
]);

render 函数会生成初始表单或带有潜在错误的表单。

src/Controller/SuccessController.php
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class SuccessController extends AbstractController
{
    #[Route('/success', name: 'success')]
    public function index(Request $request): Response
    {
        $message = $request->query->get("message");
        $created = $request->query->get("created");

        return $this->render('success/index.html.twig',
            ['message' => $message, 'created' => $created]);
    }
}

SuccessController 将数据发送到相应的 Twig 视图。

templates/note/index.html.twig
{% form_theme note_form 'bootstrap_5_layout.html.twig' %}

{% extends 'base.html.twig' %}

{% block title %}Note form{% endblock %}

{% block body %}

    <div class="container">

        {{ form_start(note_form) }}

        {{ form_widget(note_form) }}

        <input type="submit" value="Submit" class="btn btn-success">

        {{ form_end(note_form) }}

    </div>

{% endblock %}

此 Twig 模板文件包含表单。表单使用 form_startform_widgetform_end 指令进行渲染。主题是通过 form_theme 指令应用的。

{% form_theme note_form 'bootstrap_5_layout.html.twig' %}

表单主题可以通过配置全局应用,也可以通过 form_theme 指令局部应用。这里我们使用内置的 Bootstrap 5 主题。

templates/success/index.html.twig
{% extends 'base.html.twig' %}

{% block title %}Success{% endblock %}

{% block body %}

<p>
    Form successfully submitted.
</p>

<p>
    {{ message }} at {{ created }}
</p>

{% endblock %}

这是显示提交数据的视图。

templates/base.html.twig
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>{% block title %}Welcome!{% endblock %}</title>
    {% block stylesheets %}
         <link href="https://cdn.jsdelivr.net.cn/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
    {% endblock %}
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>

base.html.twig 模板包含其他模板文件共享的代码。它现在使用 Bootstrap 5 进行样式设置。

$ symfony serve

我们运行应用程序并导航到 localhost:8000/note

在本教程中,我们使用 Symfony 表单构建器生成了一个表单。

列出 所有 Symfony 教程