形式

编辑本页

警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 3.4,现已不再维护。

本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。

形式

截屏视频

你更喜欢视频教程吗?请查看ob娱乐下载Symfony窗体系列

处理HTML表单是web开发人员最常见也是最具挑战性的任务之一。ob娱乐下载Symfony集成了一个Form组件,可以帮助您处理表单。在本文中,您将从头开始构建一个复杂的表单,并在此过程中学习表单库的最重要特性。

请注意

Symfob娱乐下载ony Form组件是一个独立的库,可以在Symfony项目之外使用。有关更多信息,请参见表单组件文档欧宝官网下载app在GitHub上。

创建简单表单

假设您正在构建一个简单的待办事项列表应用程序,需要显示“任务”。因为您的用户需要编辑和创建任务,所以您需要构建一个表单。但在你开始之前,首先关注一般任务表示和存储单个任务数据的类:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/ / src / AppBundle /实体/ Task.php名称空间AppBundle实体任务受保护的任务受保护的dueDate公共函数getTask()返回->任务;}公共函数setTask任务->任务=任务;}公共函数getDueDate()返回->dueDate;}公共函数setDueDate(\ DateTimedueDate= null)->dueDate =dueDate;}}

这个类是一个“普通的老php对象”,因为到目前为止,它与Symfony或任何其他库都没有关系。ob娱乐下载它是直接解决内部问题的普通PHP对象你的应用程序(即需要在应用程序中表示任务)。在本文结束时,您将能够向a提交数据任务实例(通过HTML表单),验证其数据并将其持久化到数据库中。

构建表单

现在您已经创建了一个任务类,下一步是创建并呈现实际的HTML表单。在Syob娱乐下载mfony中,这是通过构建一个表单对象,然后在模板中呈现它来完成的。现在,这一切都可以在控制器内部完成:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/ / src / AppBundle /控制器/ DefaultController.php名称空间AppBundle控制器使用AppBundle实体任务使用ob娱乐下载FrameworkBundle控制器控制器使用ob娱乐下载组件形式扩展核心类型DateType使用ob娱乐下载组件形式扩展核心类型SubmitType使用ob娱乐下载组件形式扩展核心类型TextType使用ob娱乐下载组件HttpFoundation请求DefaultController扩展控制器公共函数newAction(请求请求//创建一个任务,并为它提供一些虚拟数据任务任务();任务->setTask (“写一篇博客”);任务->setDueDate (\ DateTime (“明天”));形式->createFormBuilder (任务->add (“任务”, TextType::类)->add (“dueDate”, DateType::类)->add (“保存”, SubmitType::类,“标签”= >“创建任务”])->getForm ();返回->呈现(“违约/ new.html.twig”, (“形式”= >形式->createView ()));}}

提示

这个示例向您展示了如何直接在控制器中构建表单。后来,在“形式部分,您将学习如何在一个独立的类中构建表单,当您的表单变得可重用时,建议您这样做。

创建表单只需要相对较少的代码,因为Symfony表单对象是用“表单构建器”构建的。ob娱乐下载表单构建器的目的是允许您编写简单的表单“食谱”,并让它完成实际构建表单的所有繁重工作。

在本例中,您向表单中添加了两个字段-任务而且dueDate-对应任务而且dueDate的属性任务类。你还为每个人分配了一个“类型”(例如:TextType而且DateType),由它的全限定类名表示。除此之外,它还决定为该字段呈现哪些HTML表单标记。

最后,您添加了一个带有自定义标签的提交按钮,用于向服务器提交表单。

ob娱乐下载Symfony附带了许多内置类型,稍后将讨论这些类型(参见形式).

渲染表单

现在已经创建了表单,下一步是呈现它。这是通过向模板传递一个特殊的表单“view”对象来实现的(注意形式- > createView ()在上面的控制器中),并使用一组表单帮助函数:

1 2 3 4
{# app /资源/视图/ / new.html违约。树枝#}{{form_start(form)}}{{form_widget(form)}}{{form_end(form)}}

请注意

本例假设您在“POST”请求中提交表单,并将其提交到显示表单的相同URL。稍后您将了解如何更改请求方法和表单的目标URL。

就是这样!只需要三行就可以呈现完整的表单:

form_start(形式)
呈现表单的开始标记,包括使用文件上传时正确的enctype属性。
form_widget(形式)
呈现所有字段,其中包括字段元素本身、标签和字段的任何验证错误消息。
form_end(形式)
呈现表单的结束标记和尚未呈现的任何字段,以防您自己呈现每个字段。这对于渲染隐藏字段和利用自动属性非常有用CSRF保护

另请参阅

虽然这么短,但不是很灵活。通常,您希望单独呈现每个表单字段,以便可以控制表单的外观。你会在"如何控制表单的渲染”一节。

在继续之前,请注意如何渲染任务字段的值任务属性中的美元的任务对象(即。“写一篇博客”)。这是表单的第一项工作:从对象中获取数据,并将其转换为适合在HTML表单中呈现的格式。

提示

表单系统足够智能,可以访问受保护的值任务通过getTask ()而且setTask ()方法任务类。除非一个属性是公共的,否则它必须有一个“getter”和“setter”方法,这样Form组件就可以获取数据并将数据放到属性上。对于一个布尔属性,你可以使用“isser”或“hasser”方法(例如:发表()hasReminder ())而不是getter(例如。个短篇()getReminder ()).

处理递交表格

默认情况下,表单会将POST请求提交回呈现它的同一个控制器。

这里,表单的第二项工作是将用户提交的数据转换回对象的属性。要做到这一点,必须将用户提交的数据写入Form对象。添加以下功能到你的控制器:

12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/ /……使用ob娱乐下载组件HttpFoundation请求公共函数newAction(请求请求//设置一个新的$task对象(删除虚拟数据)任务任务();形式->createFormBuilder (任务->add (“任务”, TextType::类)->add (“dueDate”, DateType::类)->add (“保存”, SubmitType::类,“标签”= >“创建任务”])->getForm ();形式->handleRequest (请求);如果形式->isSubmitted () & &形式->isValid ()) {// $form->getData()保存提交的值但是,原来的' $task '变量也被更新了任务形式->getData ();/ /……执行一些操作,例如将任务保存到数据库//例如,如果Task是Doctrine实体,保存它!// $entityManager = $this->getDoctrine()->getManager();/ / entityManager - >保存($任务);/ / entityManager - >冲洗();返回->redirectToRoute (“task_success”);}返回->呈现(“违约/ new.html.twig”, (“形式”= >形式->createView ()));}

谨慎

请注意createView ()方法。handleRequest ()被称为。中所做的更改* _SUBMIT事件没有应用到视图(比如验证错误)。

该控制器遵循处理表单的通用模式,有三种可能的路径:

  1. 当最初在浏览器中加载页面时,将创建并呈现表单。handleRequest ()确认表单未提交并且不执行任何操作。isSubmitted ()返回如果没有提交表格。
  2. 当用户提交表单时,handleRequest ()识别此错误并立即将提交的数据写回任务而且dueDate的属性美元的任务对象。然后验证该对象。如果它无效(验证将在下一节中讨论),isValid ()返回表单再次呈现,但现在有验证错误;
  3. 当用户提交带有有效数据的表单时,再次将提交的数据写入表单,但这一次不同isValid ()返回真正的.方法执行一些操作美元的任务对象(例如将其持久化到数据库),然后将用户重定向到其他页面(例如“谢谢”或“成功”页面)。

    请注意

    在成功提交表单后重定向用户会阻止用户点击浏览器的“刷新”按钮并重新发布数据。

另请参阅

如果需要更多地控制何时提交表单或将哪些数据传递给表单,则可以使用提交()方法。阅读更多相关信息如何使用submit()函数来处理表单提交

表单验证

在前一节中,您了解了如何提交带有有效或无效数据的表单。在Syob娱乐下载mfony中,验证应用于底层对象(例如。任务).换句话说,问题不在于“形式”是否有效,而在于“形式”是否有效美元的任务对象在表单向其应用提交的数据后有效。调用美元形式- > isValid ()是问的快捷方式美元的任务对象,无论它是否具有有效数据。

验证是通过向类添加一组规则(称为约束)来完成的。要查看实际情况,请添加验证约束,以便任务字段不能为空,且dueDate字段不能为空,必须是有效的DateTime对象。

  • 注释
  • YAML
  • XML
  • PHP
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/ / src / AppBundle /实体/ Task.php名称空间AppBundle实体使用ob娱乐下载组件验证器约束作为断言任务/ * * *@Assert\ NotBlank * /公共任务/ * * *@Assert\ NotBlank *@Assert\类型(" \ DateTime ") * /受保护的dueDate;}

就是这样!如果您使用无效数据重新提交表单,您将看到表单打印出相应的错误。

验证是Symfony的一个非常强大的特性,它有自己的特性ob娱乐下载专门的文章

多亏了HTML5,许多浏览器可以在客户端本地强制执行某些验证约束。最常见的验证是通过呈现要求属性。对于支持HTML5的浏览器,如果用户试图提交该字段为空的表单,这将导致显示本机浏览器消息。

生成的表单通过添加触发验证的合理HTML属性,充分利用了这个新特性。方法来禁用客户端验证已经属性的形式标签或formnovalidate到提交标记。当您想要测试服务器端验证约束,但浏览器阻止您提交空白字段时,这尤其有用。

1 2 3 4
{# app /资源/视图/ / new.html违约。树枝#}{{form_start(form, {'attr': {'novalidate': 'novalidate'}})}}{{form_widget(form)}}{{form_end(form)}}

内置字段类型

ob娱乐下载Symfony标准提供了一大组字段类型,涵盖了您将遇到的所有常见表单字段和数据类型:

基础领域

您还可以创建自己的自定义字段类型。看到如何创建自定义表单字段类型的信息。

字段类型选项

每个字段类型都有许多可用于配置它的选项。例如,dueDate字段目前被渲染为3个选择框。然而,DateType可以配置为呈现为单个文本框(用户将在框中输入日期作为字符串):

1
->add (“dueDate”, DateType::类,“部件”= >“single_text”])

每个字段类型都有许多可以传递给它的不同选项。其中许多是特定于字段类型的,可以在每种类型的文档中找到详细信息。欧宝官网下载app

最常见的选项是要求选项,该选项可应用于任何字段。默认情况下,要求选项设置为真正的,这意味着如果该字段为空,支持html5的浏览器将应用客户端验证。如果你也不想要这种行为禁用HTML5验证或设置要求选择你的领域

1 2 3 4
->add (“dueDate”, DateType::类,“部件”= >“single_text”“要求”= >])

还要注意设置要求选项真正的将应用服务器端验证的结果。换句话说,如果用户为字段提交了一个空白值(例如,使用旧的浏览器或web服务),它将被接受为有效值,除非您使用Symfony的ob娱乐下载NotBlankNotNull验证约束。

换句话说,要求选项是“好”,但真正的服务器端验证应该总是被使用。

属性可以设置表单字段的标签标签选项,可应用于任何字段:

1 2 3 4
->add (“dueDate”, DateType::类,“部件”= >“single_text”“标签”= >“到期日”,)

字段的标签也可以在呈现表单的模板中设置,见下文。如果不需要与输入相关联的标签,可以通过将其值设置为来禁用它

字段类型猜测

方法中添加了验证元数据任务类,Symfoob娱乐下载ny已经知道一些关于你的领域。如果您允许,Symfony可以“猜ob娱乐下载测”您的字段类型并为您设置。在本例中,Symfony可以从验证ob娱乐下载规则中猜测任务场是正常的TextType场和dueDate字段是DateType字段:

1 2 3 4 5 6 7 8 9 10
公共函数newAction()任务任务();形式->createFormBuilder (任务->add (“任务”->add (“dueDate”, (“部件”= >“single_text”])->add (“保存”, SubmitType::类)->getForm ();}

的第二个参数时,“猜测”将被激活add ()方法(或如果您通过它)。如果您传递一个选项数组作为第三个参数(done fordueDate),这些选项将应用于猜测的字段。

谨慎

如果您的表单使用特定的验证组,字段类型猜测器仍然会考虑所有猜测字段类型时的验证约束(包括不属于正在使用的验证组的约束)。

字段类型选项猜测

除了猜测字段的“类型”之外,Symfony还可以尝试猜测许多字段选项的正确值。ob娱乐下载

提示

设置了这些选项后,字段将呈现为HTML5客户端验证的特殊HTML属性。然而,它不会生成等效的服务器端约束(例如。维护\长度).尽管您需要手动添加服务器端验证,但这些字段类型选项可以从该信息中猜测出来。

要求
要求选项可以根据验证规则(即是字段)来猜测NotBlankNotNull)或Doctrine元数据(即字段可以为空).这非常有用,因为您的客户端验证将自动匹配您的验证规则。
最大长度
如果字段是某种文本字段,则最大长度选项属性可以从验证约束(如果长度范围使用)或从Doctrine元数据(通过字段的长度)。

谨慎

这些字段选项是只有猜测是否使用Symfony来猜测字段类型(即省略ob娱乐下载或传递)正如第二个论点add ()).

如果你想改变一个猜测值,你可以通过在options字段数组中传递选项来覆盖它:

1
->add (“任务”, (“attr”= > [最大长度的= >4]])

创建表单类

如您所见,可以在控制器中直接创建和使用表单。但是,更好的做法是在单独的、独立的PHP类中构建表单,这样就可以在应用程序的任何地方重用它。创建一个新类,它将容纳构建任务表单的逻辑:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/ / src / AppBundle /形式/ TaskType.php名称空间AppBundle形式使用ob娱乐下载组件形式AbstractType使用ob娱乐下载组件形式扩展核心类型SubmitType使用ob娱乐下载组件形式FormBuilderInterfaceTaskType扩展AbstractType公共函数buildForm(FormBuilderInterface构建器数组,选项构建器->add (“任务”->add (“dueDate”, (“部件”= >“single_text”])->add (“保存”, SubmitType::类);}}

这个新类包含创建任务表单所需的所有方向。它可以用于在控制器中快速构建一个表单对象:

1 2 3 4 5 6 7 8 9 10
/ / src / AppBundle /控制器/ DefaultController.php使用AppBundle形式TaskType公共函数newAction()任务=……;形式->createForm (TaskType::类,任务);/ /……

将表单逻辑放入自己的类中意味着该表单可以在项目的其他地方重用。这是创建表单的最佳方式,但最终还是取决于您。

每个表单都需要知道保存底层数据的类的名称(例如。实体AppBundle \ \任务).通常,这只是基于传递给第二个参数的对象来猜测createForm ()(即。美元的任务).之后,当您开始嵌入表单时,这将不再足够。因此,虽然并不总是必要的,但显式地指定属性通常是个好主意data_class选项,将以下内容添加到您的表单类型类:

1 2 3 4 5 6 7 8 9 10 11
/ / src / AppBundle /形式/ TaskType.php使用AppBundle实体任务使用ob娱乐下载组件OptionsResolverOptionsResolver/ /……公共函数configureOptions(OptionsResolver解析器解析器->setDefaults ([“data_class”= >任务::类,]);}

提示

将表单映射到对象时,将映射所有字段。表单上映射对象上不存在的任何字段都将导致抛出异常。

如果您需要表单中的额外字段(例如:“您是否同意这些术语”复选框)而不会映射到底层对象,则需要设置映射选项

1 2 3 4 5 6 7 8 9 10 11
使用ob娱乐下载组件形式FormBuilderInterface公共函数buildForm(FormBuilderInterface构建器数组,选项构建器->add (“任务”->add (“dueDate”->add (“agreeTerms”, CheckboxType::类,“映射”= >])->add (“保存”, SubmitType::类);}

此外,如果表单上有任何字段未包含在提交的数据中,这些字段将显式地设置为

在控制器中可以通过以下方式访问现场数据:

1
形式->get (“agreeTerms”->getData ();

此外,还可以直接修改未映射字段的数据:

1
形式->get (“agreeTerms”->setData (真正的);

请注意

表单名称是根据类型类名自动生成的。如果要修改它,请使用createNamed ()方法:

12 3 4 5 6 7 8 9 10 11 12 13 14
/ / src / AppBundle /控制器/ DefaultController.php使用AppBundle形式TaskType使用ob娱乐下载FrameworkBundle控制器AbstractControllerDefaultController扩展AbstractController公共函数newAction()任务=……;形式->get (“form.factory”->createNamed (“名字”, TaskType::类,任务);/ /……}}

您甚至可以通过将其设置为空字符串来完全抑制名称。

最终的想法

在构建表单时,请记住表单的第一个目标是从对象转换数据(任务)转换为HTML表单,以便用户可以修改该数据。表单的第二个目标是获取用户提交的数据,并将其重新应用于对象。

还有很多东西要学,还有很多强大的表单系统中的技巧。

此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。