形式
编辑本页警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 5.3,现已不再维护。
读本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。
形式
截屏视频
你更喜欢视频教程吗?请查看ob娱乐下载Symfony窗体系列.
创建和处理HTML表单是困难和重复的。您需要处理HTML表单字段的呈现、验证提交的数据、将表单数据映射到对象等等。ob娱乐下载Symfony包含一个强大的表单特性,为真正复杂的场景提供了所有这些特性和更多特性。
使用
使用Symfony表单时推荐的工作流如下:ob娱乐下载
- 构建表单在Symfob娱乐下载ony控制器中或使用专用的表单类;
- 渲染表单在模板中,这样用户可以编辑和提交它;
- 处理表单验证提交的数据,将其转换为PHP数据并对其进行处理(例如将其持久化到数据库中)。
这些步骤将在下一节中详细解释。为了使示例更容易理解,它们都假设您正在构建一个显示“任务”的小型Todo列表应用程序。
用户使用Symfony表单创建和编辑任务。ob娱乐下载每个任务都是以下任务的一个实例任务
类:
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 /实体/ Task.php名称空间应用程序\实体;类任务{受保护的$任务;受保护的$dueDate;公共函数getTask():字符串{返回$这->任务;}公共函数setTask(字符串$任务):无效{$这->任务=$任务;}公共函数getDueDate(): ? \DateTime{返回$这->dueDate;}公共函数setDueDate(?\DateTime$dueDate):无效{$这->dueDate =$dueDate;}}
这个类是一个“普通的老php对象”,因为到目前为止,它与Symfony或任何其他库都没有关系。ob娱乐下载它是直接解决内部问题的普通PHP对象你的应用程序(即需要在应用程序中表示任务)。但是你也可以编辑教义的实体用同样的方法。
表单类型
在创建第一个Symfony表单之前,理解“表单类型”的ob娱乐下载概念是很重要的。在其他项目中,区分“表单”和“表单字段”是很常见的。在Syob娱乐下载mfony中,所有这些都是“表单类型”:
- 一个单一的
< input type = " text " >
表单字段是一个“表单类型”(例如:TextType
); - 一组用于输入邮政地址的HTML字段是一种“表单类型”(例如。
PostalAddressType
); - 一个完整的
< >形式
使用多个字段来编辑用户配置文件是“表单类型”(例如。UserProfileType
).
这一开始可能会让你感到困惑,但很快你就会觉得很自然。此外,它简化了代码,使“组合”和“嵌入”表单字段更容易实现。
有几十种Symfony提供的表单类型ob娱乐下载你也可以创建自己的表单类型.
建筑形式
ob娱乐下载Symfony提供了一个“表单构建器”对象,它允许您使用一个流畅的接口来描述表单字段。稍后,此构建器创建用于呈现和处理内容的实际表单对象。
在控制器中创建表单
如果您的控制器从AbstractController,使用createFormBuilder ()
助手:
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
/ / src /控制器/ TaskController.php名称空间应用程序\控制器;使用应用程序\实体\任务;使用ob娱乐下载\包\FrameworkBundle\控制器\AbstractController;使用ob娱乐下载\组件\形式\扩展\核心\类型\DateType;使用ob娱乐下载\组件\形式\扩展\核心\类型\SubmitType;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextType;使用ob娱乐下载\组件\HttpFoundation\请求;使用ob娱乐下载\组件\HttpFoundation\响应;类TaskController扩展AbstractController{公共函数新(请求$请求):响应{//创建一个任务对象并初始化这个示例的一些数据$任务=新任务();$任务->setTask (“写一篇博客”);$任务->setDueDate (新\ DateTime (“明天”));$形式=$这->createFormBuilder ($任务)->add (“任务”, TextType::类)->add (“dueDate”, DateType::类)->add (“保存”, SubmitType::类,“标签”= >“创建任务”])->getForm ();/ /……}}
如果您的控制器没有从AbstractController
,你需要在控制器中获取服务并使用createBuilder ()
方法form.factory
服务。
在本例中,您向表单中添加了两个字段-任务
而且dueDate
-对应任务
而且dueDate
的属性任务
类。你们也给每个人分配了a表单类型(如。TextType
而且DateType
),由它的全限定类名表示。最后,您添加了一个带有自定义标签的提交按钮,用于向服务器提交表单。
创建表单类
ob娱乐下载Symfony建议在控制器中添加尽可能少的逻辑。这就是为什么最好将复杂的表单移动到专用的类中,而不是在控制器操作中定义它们。此外,类中定义的表单可以在多个操作和服务中重用。
表单类是表单类型实现FormTypeInterface.但是,最好从AbstractType,它已经实现了接口并提供了一些实用程序:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
/ / src /形式/类型/ TaskType.php名称空间应用程序\形式\类型;使用ob娱乐下载\组件\形式\AbstractType;使用ob娱乐下载\组件\形式\扩展\核心\类型\DateType;使用ob娱乐下载\组件\形式\扩展\核心\类型\SubmitType;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextType;使用ob娱乐下载\组件\形式\FormBuilderInterface;类TaskType扩展AbstractType{公共函数buildForm(FormBuilderInterface$构建器数组,$选项):无效{$构建器->add (“任务”, TextType::类)->add (“dueDate”, DateType::类)->add (“保存”, SubmitType::类);}}
提示
安装MakerBundle类来生成表单类:形式
而且:注册表单
命令。
表单类包含创建任务表单所需的所有方向。控件扩展的控制器中AbstractController,使用createForm ()
Helper(否则,使用create ()
方法form.factory
服务):
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
/ / src /控制器/ TaskController.php名称空间应用程序\控制器;使用应用程序\形式\类型\TaskType;/ /……类TaskController扩展AbstractController{公共函数新():响应{//创建一个任务对象并初始化这个示例的一些数据$任务=新任务();$任务->setTask (“写一篇博客”);$任务->setDueDate (新\ DateTime (“明天”));$形式=$这->createForm (TaskType::类,$任务);/ /……}}
每个表单都需要知道保存底层数据的类的名称(例如。应用实体\ \任务
).通常,这只是基于传递给第二个参数的对象来猜测createForm ()
(即。美元的任务
).稍后,当你开始的时候嵌入形式在美国,这将不再足够。
因此,虽然并不总是必要的,但显式地指定属性通常是个好主意data_class
选项,将以下内容添加到您的表单类型类:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/ / src /形式/类型/ TaskType.php名称空间应用程序\形式\类型;使用应用程序\实体\任务;使用ob娱乐下载\组件\OptionsResolver\OptionsResolver;/ /……类TaskType扩展AbstractType{/ /……公共函数configureOptions(OptionsResolver$解析器):无效{$解析器->setDefaults ([“data_class”= >任务::类,]);}}
呈现形式
现在表单已经创建好了,下一步是渲染它:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/ / src /控制器/ TaskController.php名称空间应用程序\控制器;使用应用程序\实体\任务;使用应用程序\形式\类型\TaskType;使用ob娱乐下载\包\FrameworkBundle\控制器\AbstractController;使用ob娱乐下载\组件\HttpFoundation\请求;使用ob娱乐下载\组件\HttpFoundation\响应;类TaskController扩展AbstractController{公共函数新(请求$请求):响应{$任务=新任务();/ /……$形式=$这->createForm (TaskType::类,$任务);返回$这->renderForm (“任务/ new.html.twig”, (“形式”= >$形式]);}}
在Symfony 5.3之前的版本中,控制ob娱乐下载器使用这种方法$ this - >渲染('……', ['form' => $form->createView()])
渲染形式。的renderForm ()
方法抽象了这个逻辑,当提交的表单无效时,它还自动在响应中设置422 HTTP状态码。
5.3
的renderForm ()
方法在Symfony 5.3中引入。ob娱乐下载
然后,用一些表单辅助函数渲染表单内容:
1 2
{/任务/ new.html #模板。树枝#}{{form(form)}}
就是这样!的形式()函数渲染所有字段而且的< >形式
开始和结束标记。默认情况下,表单方法为帖子
目标URL与显示表单的URL相同,但是两者都可以改变.
注意渲染的任务
字段的值任务
属性中的美元的任务
对象(即。“写一篇博客”)。这是表单的第一项工作:从对象中获取数据,并将其转换为适合在HTML表单中呈现的格式。
提示
表单系统足够智能,可以访问受保护的值任务
通过getTask ()
而且setTask ()
方法任务
类。除非一个属性是公共的,否则它必须有一个“getter”和“setter”方法,这样Symfony就可以获取数据并将数据放ob娱乐下载到属性上。对于一个布尔属性,你可以使用“isser”或“hasser”方法(例如:发表()
或hasReminder ()
)而不是getter(例如。个短篇()
或getReminder ()
).
尽管这个渲染很短,但它不是很灵活。通常,您需要更多地控制整个表单或其中一些字段的外观。例如,感谢与Symfony表单的引导集成ob娱乐下载你可以设置这个选项来生成与Bootstrap 5 CSS框架兼容的表单:
- YAML
- XML
- PHP
1 2 3
#配置/包/ twig.yaml枝:form_themes:(“bootstrap_5_layout.html.twig”)
的内置的Symfonob娱乐下载y表单主题包括引导3,4,5,基础5和6,以及顺风2。你也可以创建您自己的Symfony窗体主ob娱乐下载题.
除了表单主题,Symfony还允许您ob娱乐下载自定义字段呈现的方式使用多个函数分别呈现每个字段部分(小部件、标签、错误、帮助消息等)
处理形式
的推荐的处理表格的方法是使用一个操作同时呈现表单和处理表单提交。您可以使用单独的操作,但是使用一个操作可以简化所有事情,同时保持代码的简明性和可维护性。
处理表单意味着将用户提交的数据转换回对象的属性。要做到这一点,用户提交的数据必须写入到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
/ / src /控制器/ TaskController.php/ /……使用ob娱乐下载\组件\HttpFoundation\请求;类TaskController扩展AbstractController{公共函数新(请求$请求):响应{//创建一个新的$task对象(删除示例数据)$任务=新任务();$形式=$这->createForm (TaskType::类,$任务);$形式->handleRequest ($请求);如果($形式->isSubmitted () & &$形式->isValid ()) {// $form->getData()保存提交的值但是,原来的' $task '变量也被更新了$任务=$形式->getData ();/ /……执行一些操作,例如将任务保存到数据库//例如,如果Task是Doctrine实体,保存它!// $entityManager = $this->getDoctrine()->getManager();/ / entityManager - >保存($任务);/ / entityManager - >冲洗();返回$这->redirectToRoute (“task_success”);}返回$这->renderForm (“任务/ new.html.twig”, (“形式”= >$形式]);}}
该控制器遵循处理表单的通用模式,有三种可能的路径:
- 当最初在浏览器中加载页面时,表单还没有提交
形式- > isSubmitted ()
返回假
.因此,表单被创建并呈现; - 当用户提交表单时,handleRequest ()识别此错误并立即将提交的数据写回
任务
而且dueDate
的属性美元的任务
对象。然后对该对象进行验证(验证将在下一节中解释)。如果无效,isValid ()返回假
表单再次呈现,但现在有验证错误; - 当用户提交带有有效数据的表单时,再次将提交的数据写入表单,但这一次不同isValid ()返回
真正的
.方法执行一些操作美元的任务
对象(例如,将其持久化到数据库),然后将用户重定向到其他页面(例如,“谢谢”或“成功”页面);
请注意
在成功提交表单后重定向用户是一种最佳实践,它可以防止用户能够点击浏览器的“刷新”按钮并重新发布数据。
另请参阅
如果您需要更多地控制何时提交表单或将哪些数据传递给表单,那么可以这样做使用submit()方法处理表单提交.
提示
如果需要在不同模板中呈现和处理相同的表单,请使用呈现()
函数嵌入控制器处理表单的:
1
{{render(controller('App\\ controller \\TaskController::new'))}}
验证表单
在前一节中,您了解了如何提交带有有效或无效数据的表单。在Syob娱乐下载mfony中,问题不在于“形式”是否有效,而在于底层对象(美元的任务
在这个例子中)在表单应用了提交的数据之后是有效的。调用美元形式- > isValid ()
是问的快捷方式美元的任务
对象,无论它是否具有有效数据。
在使用验证之前,在应用程序中添加对它的支持:
1
$作曲家需要symfony/验证器ob娱乐下载
验证是通过向类中添加一组称为(验证)约束的规则来完成的。您可以将它们添加到实体类或表单类。
要查看第一种方法(向实体添加约束)的运行情况,请添加验证约束,以便任务
字段不能为空,并且dueDate
字段不能为空,必须是有效的DateTime
对象。
- 注释
- 属性
- YAML
- XML
- PHP
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/ / src /实体/ Task.php名称空间应用程序\实体;使用ob娱乐下载\组件\验证器\约束作为断言;类任务{/ * * *@Assert\ NotBlank * /公共$任务;/ * * *@Assert\ NotBlank *@Assert\类型(" \ DateTime ") * /受保护的$dueDate;}
就是这样!如果您使用无效数据重新提交表单,您将看到表单打印出相应的错误。
要查看第二种方法—向表单添加约束—并了解有关验证约束的更多信息,请参阅ob娱乐下载Symfony验证文档欧宝官网下载app.
表单验证消息
5.2
的legacy_error_messages
选项在Symfony 5.2中引入ob娱乐下载
表单类型具有默认的错误消息,这些错误消息比验证约束提供的错误消息更加清晰和用户友好。要启用这些新消息,请设置legacy_error_messages
选项假
:
- YAML
- XML
- PHP
1 2 3 4
#配置/包/ framework.yaml框架:形式:legacy_error_messages:假
其他常见表单特征
向表单传递选项
如果你在类中创建表单,当在控制器中构建表单时,可以将自定义选项作为的第三个可选参数传递给它createForm ()
:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21
/ / src /控制器/ TaskController.php名称空间应用程序\控制器;使用应用程序\形式\类型\TaskType;/ /……类TaskController扩展AbstractController{公共函数新():响应{$任务=新任务();//使用一些PHP逻辑来决定是否需要这个表单字段$dueDateIsRequired=……;$形式=$这->createForm (TaskType::类,$任务, (“require_due_date”= >$dueDateIsRequired]);/ /……}}
如果你现在尝试使用表单,你会看到一条错误消息:“require_due_date”选项不存在。属性声明它们接受的所有选项configureOptions ()
方法:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21 22
/ / src /形式/类型/ TaskType.php名称空间应用程序\形式\类型;使用ob娱乐下载\组件\OptionsResolver\OptionsResolver;/ /……类TaskType扩展AbstractType{/ /……公共函数configureOptions(OptionsResolver$解析器):无效{$解析器->setDefaults ([/ /……,“require_due_date”= >假]);//你也可以定义允许的类型,允许的值和// OptionsResolver组件支持的任何其他特性$解析器->setAllowedTypes (“require_due_date”,“bool”);}}
控件中的新表单选项buildForm ()
方法:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21
/ / src /形式/类型/ TaskType.php名称空间应用程序\形式\类型;使用ob娱乐下载\组件\形式\AbstractType;使用ob娱乐下载\组件\形式\扩展\核心\类型\DateType;使用ob娱乐下载\组件\形式\FormBuilderInterface;类TaskType扩展AbstractType{公共函数buildForm(FormBuilderInterface$构建器数组,$选项):无效{$构建器/ /……->add (“dueDate”, DateType::类,“要求”= >$选项[“require_due_date”],]);}/ /……}
表单类型选项
每一个表单类型具有许多配置选项,如ob娱乐下载Symfony形式类型引用.两个常用的选项是要求
而且标签
.
的要求
选项
最常见的选项是要求
选项,该选项可应用于任何字段。默认情况下,该选项设置为真正的
,这意味着支持html5的浏览器将要求您在提交表单之前填写所有字段。
如果你也不想要这种行为禁用客户端验证为整个窗体或设置要求
选项假
在一个或多个字段中:
1 2 3
->add (“dueDate”, DateType::类,“要求”= >假,)
的要求
选项不执行任何服务器端验证。如果用户为字段提交了一个空白值(例如,使用旧浏览器或web服务),它将被接受为有效值,除非您也使用Symfony的ob娱乐下载NotBlank
或NotNull
验证约束。
的标签
选项
默认情况下,表单字段的标签为人性化的属性名的版本(用户
->用户
;postalAddress
->邮寄地址
).设置标签
选项用于显式定义字段的标签:
1 2 3 4
->add (“dueDate”, DateType::类,//设置为FALSE不显示该字段的标签“标签”= >“在此之前完成”,)
提示
默认情况下,<标识>
必需字段的标记使用要求
类,所以你可以通过应用CSS样式来显示星号:
1 2 3
标签.required:在{内容:“*”;}
更改动作和HTTP方法
默认情况下,表单将通过HTTP POST请求提交到呈现表单的同一个URL。在控制器中构建表单时,使用setAction ()
而且setMethod ()
改变这一点的方法:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/ / src /控制器/ TaskController.php名称空间应用程序\控制器;/ /……使用ob娱乐下载\包\FrameworkBundle\控制器\AbstractController;使用ob娱乐下载\组件\形式\扩展\核心\类型\DateType;使用ob娱乐下载\组件\形式\扩展\核心\类型\SubmitType;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextType;类TaskController扩展AbstractController{公共函数新():响应{/ /……$形式=$这->createFormBuilder ($任务)->setAction ($这->generateUrl (“target_route”))->setMethod (“得到”)/ /……->getForm ();/ /……}}
在类中构建表单时,将动作和方法作为表单选项传递:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21
/ / src /控制器/ TaskController.php名称空间应用程序\控制器;使用应用程序\形式\TaskType;使用ob娱乐下载\包\FrameworkBundle\控制器\AbstractController;/ /……类TaskController扩展AbstractController{公共函数新():响应{/ /……$形式=$这->createForm (TaskType::类,$任务, (“行动”= >$这->generateUrl (“target_route”),“方法”= >“得到”]);/ /……}}
方法来重写模板中的操作和方法形式()
或者是form_start ()
辅助功能:
1 2
{/任务/ new.html #模板。树枝#}{{form_start(形式,{“行动”:路径(“target_route”)、“法”:“得到”})}}
请注意
如果表单的方法不是得到
或帖子
,但把
,补丁
或删除
, ob娱乐下载Symfony将插入一个包含名称的隐藏字段_method
它存储这个方法。表格将以正常的方式提交帖子
要求,但ob娱乐下载Symfony的路由能够检测_method
参数,并将其解释为把
,补丁
或删除
请求。的框架配置参考(FrameworkBundle)选项必须启用才能正常工作。
更改表单名称
如果检查所呈现表单的HTML内容,您将看到< >形式
名称和字段名是根据类型类名生成的(例如。
如果要对此进行修改,请使用createNamed ()方法:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/ / src /控制器/ TaskController.php名称空间应用程序\控制器;使用应用程序\形式\TaskType;使用ob娱乐下载\包\FrameworkBundle\控制器\AbstractController;/ /……类TaskController扩展AbstractController{公共函数新():响应{$任务=……;$形式=$这->get (“form.factory”)->createNamed (“my_name”, TaskType::类,$任务);/ /……}}
您甚至可以通过将其设置为空字符串来完全抑制名称。
客户端HTML验证
多亏了HTML5,许多浏览器可以在客户端本地强制执行某些验证约束。最常见的验证是通过添加要求
属性。对于支持HTML5的浏览器,如果用户试图提交该字段为空的表单,这将导致显示本机浏览器消息。
生成的表单通过添加触发验证的合理HTML属性,充分利用了这个新特性。方法来禁用客户端验证已经
属性的< >形式
标签或formnovalidate
到提交标记。当您想要测试服务器端验证约束,但浏览器阻止您提交空白字段时,这尤其有用。
1 2 3 4
{/任务/ new.html #模板。树枝#}{{form_start(form, {'attr': {'novalidate': 'novalidate'}})}}{{form_widget(form)}}{{form_end(form)}}
表单类型猜测
如果表单处理的对象包含验证约束,Symfony可以自省该元数据以猜测字段的类型并为您设置它。ob娱乐下载在上面的示例中,Symfony可以从验证规则ob娱乐下载中猜测任务
场是正常的TextType
场和dueDate
字段是DateType
字段。
的第二个参数add ()
方法,或pass零
到它,以启用Symfony的“猜测ob娱乐下载机制”:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21 22
/ / src /形式/类型/ TaskType.php名称空间应用程序\形式\类型;使用ob娱乐下载\组件\形式\AbstractType;使用ob娱乐下载\组件\形式\扩展\核心\类型\DateType;使用ob娱乐下载\组件\形式\扩展\核心\类型\SubmitType;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextType;使用ob娱乐下载\组件\形式\FormBuilderInterface;类TaskType扩展AbstractType{公共函数buildForm(FormBuilderInterface$构建器数组,$选项):无效{$构建器//如果没有定义字段选项,可以省略第二个参数->add (“任务”)//如果你定义了字段选项,传递NULL作为第二个参数->add (“dueDate”,零, (“要求”= >假])->add (“保存”, SubmitType::类);}}
谨慎
当使用特定的表单验证组,字段类型猜测器仍然会考虑所有猜测字段类型时的验证约束(包括不属于正在使用的验证组的约束)。
表单类型选项猜测
当对某些字段启用猜测机制时(即省略或传递)零
正如第二个论点add ()
),除了它的表格类型外,你也可以猜到以下选项:
-
要求
-
的
要求
选项可以根据验证规则(即是字段)来猜测NotBlank
或NotNull
)或Doctrine元数据(即字段可以为空
).这非常有用,因为您的客户端验证将自动匹配您的验证规则。 -
最大长度
-
如果字段是某种文本字段,则
最大长度
选项属性可以从验证约束(如果长度
或范围
)或来自the学说元数据(通过字段的长度)。
如果你想改变一个猜测值,通过在options字段数组中传递选项来覆盖它:
1
->add (“任务”,零, (“attr”= > [最大长度的= >4]])
地图上未标明的字段
当通过表单编辑对象时,所有表单字段都被认为是对象的属性。表单上任何在对象上不存在的字段都会引发异常。
如果您需要表单中的额外字段,而这些字段不会存储在对象中(例如添加一个"我同意这些条款"复选框),设置映射
选项假
在这些领域:
12 3 4 5 6 7 8 9 10 11 12 13 14 15
/ /……使用ob娱乐下载\组件\形式\FormBuilderInterface;类TaskType扩展AbstractType{公共函数buildForm(FormBuilderInterface$构建器数组,$选项):无效{$构建器->add (“任务”)->add (“dueDate”)->add (“agreeTerms”, CheckboxType::类,“映射”= >假])->add (“保存”, SubmitType::类);}}
这些“未映射字段”可以在控制器中设置和访问:
1 2
$形式->get (“agreeTerms”)->getData ();$形式->get (“agreeTerms”)->setData (真正的);
此外,如果表单上有任何字段未包含在提交的数据中,这些字段将显式地设置为零
.
了解更多
在构建表单时,请记住表单的第一个目标是从对象转换数据(任务
)转换为HTML表单,以便用户可以修改该数据。表单的第二个目标是获取用户提交的数据,并将其重新应用于对象。
还有很多东西要学,还有很多强大的Symfony形式中的技巧:ob娱乐下载
参考:
高级功能:
表单主题和定制:
事件:
验证:
Misc。