bentuk
Untuk pembangun web, memproses borang HTML ialah salah satu tugas yang paling biasa dan mencabar. Symfony menyepadukan komponen Borang untuk memudahkan pemprosesan borang. Dalam bab ini, anda akan mencipta borang yang kompleks dari awal dan mempelajari ciri penting pustaka borang.
Komponen Borang Symfony ialah perpustakaan kelas bebas yang boleh anda gunakan di luar projek Symfony anda. Rujuk Dokumentasi komponen borang untuk mengetahui lebih lanjut.
Buat borang ringkas ¶
Andaikan anda sedang membina senarai tugasan mudah untuk memaparkan beberapa "tugas". Anda perlu membuat borang untuk membenarkan pengguna anda mengedit dan membuat tugasan. Sebelum itu, mari kita lihat kelas Task
, yang boleh membuat dan menyimpan data untuk satu tugasan. Task
类,它可呈现和存储一个单一任务的数据。
// src/AppBundle/Entity/Task.phpnamespace AppBundle\Entity; class Task{ protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; }}
这是一个原生的PHP对象类,因为它没有和Symfony互动也没有引用其它类库。它是非常简单的一个PHP对象类,直接解决了 你 程序中的 task
(任务)之数据问题。当然,在本章的最后,你将能够通过HTML表单把数据提交到一个 Task
实例,验证它的值,并把它持久化到数据库。
构建表单 ¶
现在你已经创建了一个 Task
// src/AppBundle/Controller/DefaultController.phpnamespace AppBundle\Controller; use AppBundle\Entity\Task;use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\Form\Extension\Core\Type\TextType;use Symfony\Component\Form\Extension\Core\Type\DateType;use Symfony\Component\Form\Extension\Core\Type\SubmitType; class DefaultController extends Controller{ public function newAction(Request $request) { // create a task and give it some dummy data for this example // 创建一个task对象,赋一些例程中的假数据给它 $task = new Task(); $task->setTask('Write a blog post'); $task->setDueDate(new \DateTime('tomorrow')); $form = $this->createFormBuilder($task) ->add('task', TextType::class) ->add('dueDate', DateType::class) ->add('save', SubmitType::class, array('label' => 'Create Task')) ->getForm(); return $this->render('default/new.html.twig', array( 'form' => $form->createView(), )); }}Ini ialah kelas objek PHP asli, kerana ia tidak berinteraksi dengan Symfony atau merujuk perpustakaan lain. Ia ialah kelas objek PHP yang sangat mudah yang secara langsung menyelesaikan masalah data
task
(task) dalam program your. Sudah tentu, pada penghujung bab ini, anda akan dapat menyerahkan data kepada contoh Task
melalui borang HTML, mengesahkan nilainya dan mengekalkannya ke pangkalan data. Bina borang ¶
TWIG:{# app/Resources/views/default/new.html.twig #} {{ form_start(form) }} {{ form_widget(form) }} {{ form_end(form) }}
Membuat borang tidak memerlukan banyak kod kerana objek bentuk Symfony dicipta melalui "pembina borang". Tujuan pembangun borang adalah untuk membenarkan anda menulis "arahan" penciptaan borang yang ringkas dan semua tugasan "melebihi beban" semasa membuat borang dilengkapkan oleh pembina.
Dalam contoh ini, anda telah menambah dua medan pada borang, iaitu task
dan dueDate
. Sepadan dengan atribut task
dan dueDate
dalam kelas Task
. Anda telah menentukan "jenis" FQCN (Nama Kelas Penuh Penuh/nama kelas laluan penuh) untuk mereka masing-masing (seperti TextType
, DateType
), yang ditentukan oleh taip untuk menjana untuk medan teg bentuk HTML (kumpulan teg). task
和 dueDate
。对应的是 Task
类中的 task
和 dueDate
属性。你已为它们分别指定了FQCN(Full Quilified Class Name/完整路径类名)的“类型”(如 TextType
, DateType
),由类型决定为字段生成哪一种HTML表单标签(标签组)。
最后,你添加了一个带有自定义label的提交按钮以向服务器提交表单。
Symfony附带了许多内置类型,它们将被简短地介绍(见下面的内置表单类型)。
渲染表单 ¶
表单创建之后,下一步就是渲染它。这是通过传递一个特定的表单“view”对象(注意上例控制器中的 $form->createView()
方法)到你的模板,并通过一系列的表单helper function(帮助函数)来实现的。
PHP:<!-- app/Resources/views/default/new.html.php --> <?php echo $view['form']->start($form) ?> <?php echo $view['form']->widget($form) ?> <?php echo $view['form']->end($form) ?>
// ...use Symfony\Component\HttpFoundation\Request; public function newAction(Request $request){ // just setup a fresh $task object (remove the dummy data) // 直接设置一个全新$task对象(删除了假数据) $task = new Task(); $form = $this->createFormBuilder($task) ->add('task', TextType::class) ->add('dueDate', DateType::class) ->add('save', SubmitType::class, array('label' => 'Create Task')) ->getForm(); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { // $form->getData() holds the submitted values // but, the original `$task` variable has also been updated // $form->getData() 持有提交过来的值 // 但是,原始的 `$task` 变量也已被更新了 $task = $form->getData(); // ... perform some action, such as saving the task to the database // for example, if Task is a Doctrine entity, save it! // 一些操作,比如把任务存到数据库中 // 例如,如果Tast对象是一个Doctrine entity,存下它! // $em = $this->getDoctrine()->getManager(); // $em->persist($task); // $em->flush(); return $this->redirectToRoute('task_success'); } return $this->render('default/new.html.twig', array( 'form' => $form->createView(), ));}
本例假设你以"POST"请求提交表单,并且提交到和“表单显示(页面)”相同的URL。后面你将学习如何改变请求方法(request method)和表单提交后的目标URL。
就是这样!只需要三行就可以渲染出完整的form表单:
form_start(form)
- 渲染表单的开始标签,包括在使用文件上传时的正确enctype属性。
form_widget(form)
- 渲染出全部字段,包含字段元素本身,字段label以及字段验证的任何错误信息。
form_end(form)
Akhir sekali, anda menambah butang hantar dengan label tersuai untuk menyerahkan borang ke pelayan. - Symfony datang dengan beberapa jenis terbina dalam, yang akan dibincangkan secara ringkas (lihat jenis borang terbina dalam di bawah ).
Menyampaikan borang ¶
Selepas borang dibuat, langkah seterusnya ialah memberikannya. Ini dilakukan dengan menghantar objek "view" bentuk tertentu (perhatikan kaedah
$form->createView()
dalam contoh pengawal di atas) ke templat anda dan melalui satu siri fungsi pembantu borang ( fungsi pembantu) untuk mencapai. Annotations:// src/AppBundle/Entity/Task.phpnamespace AppBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Task{ /** * @Assert\NotBlank() */ public $task; /** * @Assert\NotBlank() * @Assert\Type("\DateTime") */ protected $dueDate;}
YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Task: properties: task: - NotBlank: ~ dueDate: - NotBlank: ~ - Type: \DateTime

- 🎜
form_start(form)
🎜🎜Renderkan teg permulaan borang, termasuk semasa menggunakan Atribut enctype yang betul semasa memuat naik fail. 🎜🎜form_widget(form)
🎜🎜Memberikan semua medan, termasuk elemen medan itu sendiri, label medan dan sebarang maklumat ralat untuk pengesahan medan. 🎜🎜form_end(form)
🎜🎜Apabila anda menjana setiap medan secara manual, ia boleh menjadikan teg penamat borang dan semua medan dalam borang yang masih belum dipaparkan. Ini berguna apabila memaparkan medan tersembunyi dan memanfaatkan automatik
🎜🎜Perlindungan CSRF🎜🎜 Sangat berguna apabila melindungi mekanisme. 🎜🎜🎜🎜🎜Ia semudah itu, tetapi tidak begitu fleksibel (buat masa ini). Biasanya, anda ingin menjadikan setiap medan dalam bentuk secara individu untuk mengawal gaya borang. Anda akan menguasai kaedah ini dalam artikel seterusnya 🎜Cara Mengawal Rendering Borang🎜. 🎜🎜🎜Sebelum meneruskan, sila ambil perhatian mengapa kotak input task
yang diberikan mempunyai nilai sifat daripada objek $task
(iaitu "Tulis catatan blog"). Ini ialah tugas pertama borang: mendapatkan data daripada objek dan menukarnya kepada format yang sesuai supaya ia boleh dipaparkan dalam bentuk HTML. task
输入框中有一个来自 $task
对象的属性值(即“Write a blog post”)。这是表单的第一个任务:从一个对象中获取数据并把它转换成一种适当的格式,以便在HTML表单中被渲染。
表单系统足够智能,它们通过 getTask()
和 setTask()
方法来访问 Task
类中受保护的 task
属性。除非是public属性,否则 必须 有一个 "getter" 和 "setter" 方法被定义,以便表单组件能从这些属性中获取和写入数据。对于布尔型的属性,你可以使用一个 "isser" 和 "hasser" 方法(如 isPublished()
和 hasReminder()
)来替代getter方法(getPublished()
和 getReminder()
)。
处理表单提交 ¶
默认时,表单会把POST请求,向“渲染它的同一个控制器”提交回去。
此处,表单的第二个任务就是把用户提交的数据传回到一个对象的属性之中。要做到这一点,用户提交的数据必须写入表单对象才行。向控制器(Controller)中添加以下功能:
XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8"?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd"> <class name="AppBundle\Entity\Task"> <property name="task"> <constraint name="NotBlank" /> </property> <property name="dueDate"> <constraint name="NotBlank" /> <constraint name="Type">\DateTime</constraint> </property> </class></constraint-mapping>
注意 createView()
方法应该在 handleRequest
被调用 之后 再调用。否则,针对 *_SUBMIT
getTask()
dan setTask( )
untuk mengakses harta task
yang dilindungi dalam kelas Task
. Melainkan ia adalah harta awam, mesti mempunyai kaedah "pengambil" dan "penetap" yang ditakrifkan supaya komponen borang boleh mendapatkan dan menulis data daripada sifat ini. Untuk sifat boolean, anda boleh menggunakan kaedah "isser" dan "hasser" (seperti isPublished()
dan hasReminder()
) dan bukannya kaedah getter ( getPublished()
dan getReminder()
). Memproses penyerahan borang ¶
🎜Secara lalai, borang akan menghantar permintaan POST kepada " Render Ia pengawal yang sama" diserahkan kembali. 🎜🎜Di sini, tugas kedua borang adalah untuk memindahkan data yang diserahkan oleh pengguna kembali ke sifat objek. Untuk melakukan ini, data yang diserahkan oleh pengguna mesti ditulis ke objek borang. Tambahkan fungsi berikut pada Pengawal: 🎜PHP:// src/AppBundle/Entity/Task.phpuse Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints\NotBlank;use Symfony\Component\Validator\Constraints\Type; class Task{ // ... public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('task', new NotBlank()); $metadata->addPropertyConstraint('dueDate', new NotBlank()); $metadata->addPropertyConstraint( 'dueDate', new Type('\DateTime') ); }}🎜🎜
createView()
harus dipanggil dalam handleRequest
Panggil selepas sekali lagi. Jika tidak, pengubahsuaian pada acara borang *_SUBMIT
tidak akan digunakan pada lapisan paparan (seperti mesej ralat semasa pengesahan). 🎜🎜Pengawal mengikut corak biasa semasa memproses borang Ia mempunyai tiga cara yang mungkin:
#🎜🎜 #- Apabila. pelayar pada mulanya memuatkan halaman, borang dibuat dan diberikan.
handleRequest()
menyedari bahawa borang itu belum diserahkan dan tidak melakukan apa-apa. Jika borang tidak diserahkan,isSubmitted()
mengembalikan palsu; 当用户提交表单时,
handleRequest()
会识别这个动作并立即将提交的数据写入到$task
对象的task
anddueDate
属性。然后该对象被验证。如果它是无效的(验证在下一章),isValid()
会返回false
,进而表单被再次渲染,只是这次有验证错误;当用户以合法数据提交表单的时,提交的数据会被再次写入到表单,但这一次
Apabila pengguna menyerahkan borang,isValid()
返回true
。在把用户重定向到其他一些页面之前(如一个“谢谢”或“成功”的页面),你有机会用$task
handleRequest() akan mengenali tindakan ini dan segera menulis data yang diserahkan kepada tugasan<
$task
objek. /code> dan atributdueDate
. Objek itu kemudiannya disahkan. Jika ia tidak sah (pengesahan adalah dalam bab seterusnya),isValid()
akan mengembalikanfalse
dan borang akan dipaparkan sekali lagi, tetapi Terdapat ralat pengesahan kali ini;#🎜🎜#Mengubah hala pengguna selepas borang berjaya diserahkan adalah untuk menghalang pengguna daripada menghantar data berulang kali melalui butang "refresh" pelayar. #🎜🎜##🎜🎜##🎜🎜#Apabila pengguna menyerahkan borang dengan data undang-undang, data yang diserahkan akan ditulis semula ke borang, tetapi ini masa
isValid()
mengembalikantrue
. Sebelum mengubah hala pengguna ke beberapa halaman lain (seperti halaman "Terima kasih" atau "Berjaya"), anda mempunyai peluang untuk menggunakan objek$task
untuk melaksanakan beberapa operasi ( seperti meneruskannya ke pangkalan data).
handleRequest()
意识到表单没有被提交进而什么都不做。如果表单未被提交,isSubmitted()
返回false;Jika anda perlu mengawal dengan tepat apabila borang diserahkan, atau data yang dihantar ke borang, anda boleh menggunakan submit(). Untuk maklumat lanjut, sila rujuk Panggilan secara manual Borang::submit().
Pengesahan Borang ¶
Dalam bahagian sebelumnya, anda mengetahui cara borang dengan data yang sah atau tidak sah diserahkan. Dalam Symfony, proses pengesahan dilakukan dalam objek asas (seperti Task
). Dalam erti kata lain, isunya bukanlah sama ada "borang" itu sah, tetapi sama ada objek $task
adalah sah selepas "data yang diserahkan digunakan pada borang". Memanggil $form->isvalid()
ialah jalan pintas untuk menanyakan objek $task
yang mendasari sama ada ia memperoleh data yang sah. Task
)。换句话说,问题不在于“表单”是否有效,而是 $task
对象在“提交的数据应用到表单”之后是否合法。调用 $form->isvalid()
是一个快捷方式,询问底层 $task
对象是否获得了合法数据。
验证(validation)是通过把一组规则(称之为“constraints/约束”)添加到一个类中来完成的。我们给 Task
类添加规则和约束,使task属性不能为空, duDate
字段不空且必须是一个有效的DateTime对象。
PHP:<!-- app/Resources/views/default/new.html.php --><?php echo $view['form']->form($form, array( 'attr' => array('novalidate' => 'novalidate'),)) ?>
Twig:{# app/Resources/views/default/new.html.twig #} {{ form(form, {'attr': {'novalidate': 'novalidate'}}) }}
1
->add('dueDate', DateType::class, array('widget' => 'single_text'))
就是这样!如果你现在重新以非法数据提交表单,你将会看到相应的错误被输出到表单。
验证是Symfony一个非常强大的功能,它拥有自己的专属章节。