本文主要介紹了Symfony2框架學(xué)習(xí)筆記之表單用法,結(jié)合實(shí)例形式詳細(xì)分析了Symfony2針對(duì)表單的創(chuàng)建、校驗(yàn)、提交等各種常用技巧。需要的朋友可以參考下,希望對(duì)大家有所幫助。
對(duì)于一個(gè)Web開(kāi)發(fā)者來(lái)說(shuō),處理HTML表單是一個(gè)最為普通又具挑戰(zhàn)的任務(wù)。Symfony2集成了一個(gè)Form組件,讓處理表單變的容易起來(lái)。在這一節(jié)里,我們將從基礎(chǔ)開(kāi)始創(chuàng)建一個(gè)復(fù)雜的表單,學(xué)習(xí)表單類庫(kù)中最重要的內(nèi)容。
Symfony2 的Form組件是一個(gè)獨(dú)立的類庫(kù),你可以在Symfony2項(xiàng)目之外使用它。
創(chuàng)建一個(gè)簡(jiǎn)單的表單:
假設(shè)你要?jiǎng)?chuàng)建一個(gè)應(yīng)用程序的todo列表,需要顯示一些任務(wù)。因?yàn)槟愕挠脩粜枰庉嫼蛣?chuàng)建任務(wù),所以你需要?jiǎng)?chuàng)建一個(gè)表單。在你開(kāi)始之前,首先來(lái)看通用的Task類,用來(lái)表示和存儲(chǔ)一個(gè)單一任務(wù)的數(shù)據(jù):
// src/Acme/TaskBundle/Entity/Task.php namespace Acme\TaskBundle\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; } }
如果你是按照我們提供的示例編碼,那么你需要先創(chuàng)建一個(gè)AcmeTaskBundle:
$ php app/console generate:bundle --namespace=Acme/TaskBundle
該類是一個(gè)普通的PHP對(duì)象類,因?yàn)樗麄儧](méi)有任何Symfony或者其它類庫(kù)引用。非常簡(jiǎn)單的一個(gè)PHP對(duì)象類,它直接解決的是你程序中表現(xiàn)task的數(shù)據(jù)。當(dāng)然,在本節(jié)的最后,你將能夠通過(guò)HTML表單提交一個(gè)Task實(shí)例數(shù)據(jù),校驗(yàn)它的數(shù)值,并把它持久化到數(shù)據(jù)庫(kù)。
創(chuàng)建一個(gè)Form
現(xiàn)在已經(jīng)創(chuàng)建了一個(gè)Task類,下一步就是創(chuàng)建和渲染一個(gè)真正的HTML表單了。在symfony2中,它是通過(guò)創(chuàng)建一個(gè)表單對(duì)象并渲染到模板的?,F(xiàn)在,可以從controller內(nèi)部處理form。
//src/Acme/TaskBundle/Controller/DefaultController.php namespace Acme\TaskBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Acme\TaskBundle\Entity\Task; class DefaultController extends Controller { //創(chuàng)建一個(gè)任務(wù)并給它一些假數(shù)據(jù)作為示例 $task = new Task(); $task->setTask('Write a blog post'); $task->setDueDate(new \DateTime('tomorrow')); $form = $this->createFormBuilder($task) ->add('task','text') ->add('dueDate','date') ->getForm(); return $this->render('AcmeTaskBundle:Default:new.html.twig',array( 'form' =>$form->createView(), )); }
上面的示例顯示了如何直接在Controller中創(chuàng)建一個(gè)表單,為了可以讓表單重用你完全可以在一個(gè)單獨(dú)的類文件中創(chuàng)建表單。
因?yàn)镾ymfony2通過(guò)一個(gè)表單生成器“form builder"來(lái)創(chuàng)建表單對(duì)象,所以你可以使用很少的代碼就能完成創(chuàng)建表單任務(wù)。表單生成器的目的是讓你能編寫(xiě)簡(jiǎn)單的表單創(chuàng)建方法,讓它來(lái)負(fù)責(zé)繁重的創(chuàng)建任務(wù)。
在這個(gè)示例中,你已經(jīng)添加了兩個(gè)字段到你的表單,一個(gè)是task一個(gè)是dueDate。它們關(guān)聯(lián)到Task類的task和dueDate屬性。你已經(jīng)為它們分別指定了類型(比如,text,date等),由這些類型來(lái)決定為這些字段生成什么樣的HTML表單標(biāo)簽。
Symfony2 擁有許多內(nèi)建的類型,接下來(lái)我們將簡(jiǎn)單的介紹。
渲染一個(gè)表單
表單創(chuàng)建以后,下一步就是渲染它。這是通過(guò)傳遞一個(gè)特定的表單”view"對(duì)象(就是上例中的 $form->createView()返回的view對(duì)象)到你的模板并通過(guò)一些列的表單幫助函數(shù)來(lái)實(shí)現(xiàn)的。
Twig格式:
{# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #} <form action="{{ path('task_new') }}" method ="post" {{ form_enctype(form) }}> {{ form_widget(form) }} <input type="submit" /> </form>
PHP代碼格式:
<!-- src/Acme/TaskBundle/Resources/views/Default/new.html.php --> <form action="<?php echo $view['router']->generate('task_new') ?>" method="post" <?php echo $view['form']->enctype($form) ?> > <?php echo $view['form']->widget($form) ?> <input type="submit" /> </form>
在這里假設(shè)你已經(jīng)創(chuàng)建了一個(gè)名叫task_new的路由指向AcmeTaskBundle:Default:new Controller。
就是這些了,通過(guò)打印form_widget(form),表單中的每個(gè)字段都會(huì)被渲染出來(lái)。同時(shí)還有一個(gè)文本標(biāo)簽和錯(cuò)誤信息。是不是很簡(jiǎn)單,不過(guò)現(xiàn)在它還不夠靈活。通常情況下,我們渴望單獨(dú)渲染表單中的每一個(gè)字段,這樣我們可以更好的控制表單的樣式。我們會(huì)在在模板中渲染表單一節(jié)介紹。
在繼續(xù)下去之前,我們注意到,為什么我們渲染出來(lái)的task輸入框中有一個(gè)來(lái)自$task對(duì)象的屬性值“Write a blog post"。這是表單的第一個(gè)工作:從一個(gè)對(duì)象中獲取數(shù)據(jù)并把它轉(zhuǎn)換為合適的格式渲染到一個(gè)HTML表單中。
注意,表單系統(tǒng)已經(jīng)足夠聰明,它們能夠通過(guò)像getTask()和setTask()方法來(lái)訪問(wèn)Task類中受保護(hù)的屬性task。除非一個(gè)是公共屬性,否則必須有一個(gè)getter和setter方法被定義來(lái)用于表單組件從這些屬性中獲取和保持?jǐn)?shù)據(jù)。對(duì)于布爾型的屬性,你可以使用一個(gè)”isser"方法(比如 isPublished())替代getter方法(getPublished())。
處理表單提交
表單系統(tǒng)的第二個(gè)任務(wù)就是傳遞用戶提交的數(shù)據(jù)回到一個(gè)對(duì)象的屬性中。要做到這一點(diǎn),用戶提交的數(shù)據(jù)必須綁定到表單才行。添加如下代碼到你的Controller類:
//... public function newAction(Request $request) { //只是創(chuàng)建一個(gè)新的$task對(duì)象(不需要假數(shù)據(jù)) $task = new Task(); $form= $this->createFormBuilder($task) ->add('task','text') ->add('dueDate','date') ->getForm(); if($request->getMethod() == "POST"){ $form->bindRequest($request); if($form->isValid()){ //執(zhí)行一些行為,比如保持task到數(shù)據(jù)庫(kù) return $this->redirect($this->generateUrl('task_success')); } } //... }
現(xiàn)在,當(dāng)表單被提交時(shí),Controller可以綁定被提交的數(shù)據(jù)到表單,表單會(huì)把數(shù)據(jù)傳回$task對(duì)象的task和dueDate屬性。這些都在bindRequest()方法中完成。只要bindRequest()方法被調(diào)用,提交的數(shù)據(jù)就會(huì)立刻被傳輸?shù)降讓訉?duì)象。不管數(shù)據(jù)是否被真正的校驗(yàn)通過(guò)。
controller一般會(huì)遵循一個(gè)通用的模式來(lái)處理表單,它有三個(gè)可能的途徑:
1.當(dāng)在瀏覽器初始加載一個(gè)頁(yè)面時(shí),請(qǐng)求方法是GET,表單處理僅僅是創(chuàng)建和渲染。
2.當(dāng)用戶提交帶有不合法數(shù)據(jù)的表單(方法為POST)時(shí),表單會(huì)并綁定然后渲染,這時(shí)候顯示所有校驗(yàn)錯(cuò)誤。
3.當(dāng)用戶提交的表單帶有的數(shù)據(jù)均合法時(shí),表單綁定并且在頁(yè)面跳轉(zhuǎn)之前你有機(jī)會(huì)去使用數(shù)據(jù)去執(zhí)行一些業(yè)務(wù)邏輯活動(dòng),比如持久化它到數(shù)據(jù)庫(kù))。
表單校驗(yàn)
在前面我們提到了,如何提交一個(gè)帶有合法數(shù)據(jù)和非法數(shù)據(jù)的表單。在Symfony2中,校驗(yàn)是在底層對(duì)象上進(jìn)行的。換句話說(shuō),form表單合法與否不重要,主要看在表單提交數(shù)據(jù)以后,底層對(duì)象比如$task對(duì)象是否合法。調(diào)用$form->isvalid() 是一個(gè)詢問(wèn)底層對(duì)象是否獲得合法數(shù)據(jù)的快捷方式。
校驗(yàn)是通過(guò)添加一些列規(guī)則(約束)到一個(gè)類來(lái)完成的。我們給Task類添加規(guī)則和約束,使它的task屬性不能為空,duDate字段不能空并且是一個(gè)合法的DateTime對(duì)象。
YAML格式:
# Acme/TaskBundle/Resources/config/validation.yml Acme\TaskBundle\Entity\Task: properties: task: - NotBlank: ~ dueDate: - NotBlank: ~ - Type: \DateTime
在Task類中聲明格式:
// Acme/TaskBundle/Entity/Task.php use Symfony\Component\Validator\Constraints as Assert; class Task { /** * @Assert\NotBlank() */ public $task; /** * @Assert\NotBlank() * @Assert\Type("\DateTime") */ protected $dueDate; }
XML格式:
<!-- Acme/TaskBundle/Resources/config/validation.xml --> <class name="Acme\TaskBundle\Entity\Task"> <property name="task"> <constraint name="NotBlank" /> </property> <property name="dueDate"> <constraint name="NotBlank" /> <constraint name="Type"> <value>\DateTime</value> </constraint> </property> </class>
PHP代碼格式:
// Acme/TaskBundle/Entity/Task.php use 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')); } }
就是這樣了,如果你現(xiàn)在再提交包含非法數(shù)據(jù)的表單,你將會(huì)看到相應(yīng)的錯(cuò)誤被打印在表單上。
HTML5 校驗(yàn)
作為HTML5,許多瀏覽器都加強(qiáng)了客戶端某些校驗(yàn)約束。最常用的校驗(yàn)活動(dòng)是在一個(gè)必須的字段上渲染一個(gè)required屬性。對(duì)于支持HTML5的瀏覽器來(lái)說(shuō),如果用戶此時(shí)提交一個(gè)空字段到表單時(shí),瀏覽器會(huì)顯示提示信息。生成的表單廣泛吸收了這些新內(nèi)容的優(yōu)點(diǎn),通過(guò)添加一些HTML屬性來(lái)監(jiān)控校驗(yàn)??蛻舳诵r?yàn)可以通過(guò)添加novalidate屬性到form標(biāo)簽或者formnovalidate 到提交標(biāo)簽而關(guān)閉。這對(duì)你想檢查服務(wù)端校驗(yàn)規(guī)則時(shí)非常有用。
校驗(yàn)分組
如果你的對(duì)象想從校驗(yàn)組中受益,你需要指定你的表單使用哪個(gè)校驗(yàn)組。
$form = $this->createFormBuilder($users, array( 'validation_groups' => array('registration'), ))->add(...) ;
如果你創(chuàng)建表單類,你需要添加羨慕的getDefaultOptions()方法:
public function getDefaultOptions(array $options) { return array( 'validation_groups' => array('registration') ); }
在這兩種情況下,只有registration 校驗(yàn)組將被用于校驗(yàn)底層對(duì)象。
內(nèi)建字段類型
Symfony標(biāo)準(zhǔn)版含有大量的字段類型,它們幾乎涵蓋了所有通用表單的字段和數(shù)據(jù)類型。
文本字段:
text
textarea
email
integer
money
number
password
percent
search
url
選擇字段:
choice
entity
country
language
locale
timezone
日期和時(shí)間字段:
date
datetime
time
birthday
其它字段:
checkbox
file
radio
字段組:
collection
repeated
隱藏字段:
hidden
csrf
基礎(chǔ)字段:
field
form
當(dāng)然,你也可以定義自己的字段類型。
字段類型選項(xiàng)
每一個(gè)字段類型都有一定數(shù)量的選項(xiàng)用于配置。比如,dueDate字段當(dāng)前被渲染成3個(gè)選擇框。而日期字段可以被配置渲染成一個(gè)單一的文本框,用戶可以輸入字符串作為日期。
->add('dueData','data', array('widget' = 'single_text'))
required選項(xiàng):
最常用到的選項(xiàng)是required選項(xiàng),它可以應(yīng)用于任何字段。默認(rèn)情況下它被設(shè)置為true。這就意味著支持HTML5的瀏覽器會(huì)使用客戶端校驗(yàn)來(lái)判斷字段是否為空。如果你不想讓它發(fā)生,或者把在你的字段上把required選項(xiàng)設(shè)置為false,或者關(guān)閉HTML5校驗(yàn)。設(shè)置required為true并不意味著服務(wù)端校驗(yàn)被應(yīng)用。換句話說(shuō),如果用戶提交一個(gè)空數(shù)值到該字段,它將接受這個(gè)控制除非你使用Symfony的NotBlank或者NotNull校驗(yàn)約束。也就是說(shuō),required選項(xiàng)是很好,但是服務(wù)端校驗(yàn)還是要繼續(xù)用。
label選項(xiàng):
表單字段可以使用label選項(xiàng)設(shè)置顯示字符標(biāo)簽,可以應(yīng)用于任何字段:
->add('dueDate', 'date',array( 'widget' =>'single_text', 'label' => 'Due Date', ))
字段類型猜測(cè):
現(xiàn)在你已經(jīng)添加了校驗(yàn)元數(shù)據(jù)到Task類,Symfony早已經(jīng)了解一點(diǎn)關(guān)于你的字段了。如果你允許,Symfony可以猜到你的字段數(shù)據(jù)類型并為你設(shè)置它。在下面的例子中,Symfony可以根據(jù)校驗(yàn)規(guī)則猜測(cè)到task字段是一個(gè)標(biāo)準(zhǔn)的text字段,dueDate是date字段。
public function newAction() { $task = new Task(); $form = $this->createFormBuilder($task) ->add('task') ->add('dueDate', null, array('widget' => 'single_text')) ->getForm(); }
當(dāng)你省略了add方法的第二個(gè)參數(shù)(或者你輸入null)時(shí),Symfony的猜測(cè)能力就起作用了。如果你輸入一個(gè)選項(xiàng)數(shù)組作為第三個(gè)參數(shù)(比如上面的dueDate),那么這些選項(xiàng)會(huì)成為Symfony猜測(cè)的依據(jù)。如果你的表單使用了指定的校驗(yàn)數(shù)組,字段類型猜測(cè)器將還是要考慮所有的校驗(yàn)規(guī)則來(lái)綜合猜測(cè)你的字段類型。
字段類型可選項(xiàng)猜測(cè)
除了猜測(cè)字段類型,Symfony還能是這猜測(cè)一些可選項(xiàng)字段值。當(dāng)這些可選項(xiàng)被設(shè)置時(shí),字段將會(huì)被渲染到特定HTML屬性中,讓HTML5客戶端來(lái)提供校驗(yàn)。
然而,它們不會(huì)在服務(wù)端生成相應(yīng)的校驗(yàn)規(guī)則。盡管你需要手動(dòng)的在服務(wù)端添加這些規(guī)則,但是這些字段類型選項(xiàng)還是能根據(jù)這些信息猜測(cè)到。
required: required規(guī)則可以在校驗(yàn)規(guī)則或者Doctrine元數(shù)據(jù)的基礎(chǔ)上猜測(cè)到。這當(dāng)你的客戶端校驗(yàn)將自動(dòng)匹配你的校驗(yàn)規(guī)則時(shí)很有用。
max_length: 如果字段是一些列文本字段,那么max_length選項(xiàng)可以從校驗(yàn)規(guī)則或者Doctrine元數(shù)據(jù)中猜到。
如果你喜歡改變一個(gè)猜到的數(shù)值,你可以通過(guò)在可選項(xiàng)數(shù)組中傳遞該選項(xiàng)來(lái)重寫(xiě)它。
->add('task',null, array('max_length'=>4))
在模板中渲染表單
到目前為止,我們已經(jīng)看了一個(gè)完整的表單是如何通過(guò)一行代碼被渲染的。當(dāng)然,你通常需要更加靈活的渲染方式:
Twig格式:
{# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #} <form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}> {{ form_errors(form) }} {{ form_row(form.task) }} {{ form_row(form.dueDate) }} {{ form_rest(form) }} <input type="submit" /> </form>
PHP代碼格式:
<!-- // src/Acme/TaskBundle/Resources/views/Default/newAction.html.php --> <form action="<?php echo $view['router']->generate('task_new') ?>" method="post" <?php echo $view['form']->enctype($form) ?>> <?php echo $view['form']->errors($form) ?> <?php echo $view['form']->row($form['task']) ?> <?php echo $view['form']->row($form['dueDate']) ?> <?php echo $view['form']->rest($form) ?> <input type="submit" /> </form>
讓我們看看這組代碼的詳細(xì):
form_enctype(form) 只要有一個(gè)字段是文件上傳,那么它就會(huì)義務(wù)的設(shè)置為 enctype="multipart/form-data";
form_errors(form) 渲染任何整個(gè)form的任何錯(cuò)誤信息(特定字段的錯(cuò)誤,會(huì)顯示在每個(gè)字段的下面一行)。
form_row(form.dueDate) 默認(rèn)情況下,為給定的字段在一個(gè)p中渲染一個(gè)文本標(biāo)簽,任何錯(cuò)誤,和HTML表單部件。
form_rest(form) 渲染沒(méi)有指出的其余任何字段,通常在表單的末尾調(diào)用它防止遺忘或者渲染一些你不愿意手動(dòng)設(shè)置的隱藏字段。它同時(shí)還能為我們提供CSRF保護(hù)。
大部分工作是由form_row幫助方法類完成的,它默認(rèn)在一個(gè)p中為每個(gè)字段渲染顯示標(biāo)簽,錯(cuò)誤信息和HTML表單部件。
注意,你可以通過(guò)form.vars.value 來(lái)訪問(wèn)你當(dāng)前是表當(dāng)數(shù)據(jù):
Twig格式:
{{ form.vars.value.task }}
PHP代碼格式:
<?php echo $view['form']->get('value')->getTask() ?>
手工渲染每一個(gè)表單字段
form_row幫助器能讓你很快的渲染你表單中的每一個(gè)字段,并且每一行可以被自定義化。但是生活不總是那么簡(jiǎn)單的,你也可能要手動(dòng)的渲染每一個(gè)字段。
Twig格式:
{{ form_errors(form) }} <p> {{ form_label(form.task) }} {{ form_errors(form.task) }} {{ form_widget(form.task) }} </p> <p> {{ form_label(form.dueDate) }} {{ form_errors(form.dueDate) }} {{ form_widget(form.dueDate) }} </p> {{ form_rest(form) }}
PHP代碼格式:
<?php echo $view['form']->errors($form) ?> <p> <?php echo $view['form']->label($form['task']) ?> <?php echo $view['form']->errors($form['task']) ?> <?php echo $view['form']->widget($form['task']) ?> </p> <p> <?php echo $view['form']->label($form['dueDate']) ?> <?php echo $view['form']->errors($form['dueDate']) ?> <?php echo $view['form']->widget($form['dueDate']) ?> </p> <?php echo $view['form']->rest($form) ?>
如果自動(dòng)生成顯示標(biāo)簽不準(zhǔn)確,那么你可以顯式的指定它:
Twig格式:
{{ form_label(form.task, 'Task Description') }}
PHP代碼格式:
<?php echo $view['form']->label($form['task'], 'Task Description') ?>
一些字段類型有一些額外的渲染選項(xiàng)可以傳入widget,一個(gè)常用的選項(xiàng)為attr,它允許你修改表單元素的屬性。下面的示例將添加task_field class到渲染的文本輸入字段:
Twig格式:
{{ form_widget(form.task, {'attr': {'class':'task_field'} }) }}
PHP代碼格式:
<?php echo $view['form']->widget($form['task'], array( 'attr' => array('class' => 'task_field'), )) ?>
如果你想手工渲染表單字段,你可以單獨(dú)訪問(wèn)每個(gè)字段的值,比如id,name和label,這里我們獲取id
Twig格式:
{{ form.task.vars.id }}
PHP代碼格式:
<?php echo $form['task']->get('id') ?>
需要獲取表單字段名稱屬性你需要使用full_name值:
Twig格式:
{{ form.task.vars.full_name }}
PHP代碼格式:
<?php echo $form['task']->get('full_name') ?>
創(chuàng)建表單類
正如你看到的,一個(gè)表單可以直接在controller類中被創(chuàng)建和使用。然而,一個(gè)更好的做法是在一個(gè)單獨(dú)的PHP類中創(chuàng)建表單。它可以被重用到你應(yīng)用程序的任何地方。創(chuàng)建一個(gè)新類來(lái)保存生成task表單的邏輯:
// src/Acme/TaskBundle/Form/Type/TaskType.php namespace Acme\TaskBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; class TaskType extends AbstractType { public function buildForm(FormBuilder $builder, array $options) { $builder->add('task'); $builder->add('dueDate', null, array('widget' => 'single_text')); } public function getName() { return 'task'; } }
這個(gè)新類包含了所有創(chuàng)建一個(gè)task表單所需要的內(nèi)容,注意getName()方法將返回一個(gè)該表單類型的唯一標(biāo)識(shí),用于快速創(chuàng)建該表單。
// src/Acme/TaskBundle/Controller/DefaultController.php // 在類上添加這個(gè)新的引用語(yǔ)句 use Acme\TaskBundle\Form\Type\TaskType; public function newAction() { $task = // ... $form = $this->createForm(new TaskType(), $task); // ... }
設(shè)置data_class
每個(gè)表單都需要知道它底層保存數(shù)據(jù)的類名稱,(比如Acme\TaskBundle\Entity\Task)。通常情況下,是根據(jù)createForm方法的第二個(gè)參數(shù)來(lái)猜測(cè)的。以后,當(dāng)你開(kāi)始嵌入表單時(shí),這個(gè)可能就不怎么充分了,所以,通常一個(gè)好的方法是通過(guò)添加下面代碼到你的表單類型類來(lái)顯式的指定data_class 選項(xiàng)。
public function getDefaultOptions(array $options) { return array( 'data_class' => 'Acme\TaskBundle\Entity\Task', ); }
當(dāng)然,這種做法也不總是必須的。
當(dāng)你映射表單到一個(gè)對(duì)象是,所有的字段都被映射。 表單的任何字段如果在映射的對(duì)象上不存在那么就會(huì)造成拋出異常。在這種情況下,你需要在表單中獲取字段(比如,一個(gè)“你同意這些說(shuō)法嗎?”復(fù)選框)將不能映射到底層對(duì)象,那么你需要設(shè)置property_path為false以避免拋出異常。
public function buildForm(FormBuilder $builder, array $options) { $builder->add('task'); $builder->add('dueDate', null, array('property_path' => false)); }
另外,如果有任何的表單字段沒(méi)有被包含著提交的數(shù)據(jù)中,那么這些字段需要顯式的設(shè)置為null。
在controller類中我們可以訪問(wèn)字段數(shù)據(jù):
$form->get('dueDate')->getData();
Forms和Doctrine
表單的目的是把數(shù)據(jù)從一個(gè)底層對(duì)象傳遞給一個(gè)HTML表單然后把用戶提交的數(shù)據(jù)傳回到原先的底層對(duì)象。因此,底層對(duì)象把數(shù)據(jù)持久化到數(shù)據(jù)庫(kù)就跟表單沒(méi)有任何的關(guān)系了。但是,如果你已經(jīng)配置了底層類是通過(guò)Doctrine來(lái)持久化,(你已經(jīng)定義了映射元數(shù)據(jù)在底層類),接下來(lái)當(dāng)表單提交數(shù)據(jù)后,當(dāng)表單合法后就可以持久化它了。
if ($form->isValid()) { $em = $this->getDoctrine()->getEntityManager(); $em->persist($task); $em->flush(); return $this->redirect($this->generateUrl('task_success')); }
如果處于某種原因,你不想訪問(wèn)原有的$task對(duì)象,你可以從表單中直接獲取數(shù)據(jù):
$task = $form->getData();
在這里,關(guān)鍵要理解當(dāng)表單跟底層對(duì)象綁定后,用戶提交的數(shù)據(jù)會(huì)立刻傳遞給底層對(duì)象。如果你想持久化這些數(shù)據(jù),你只需要持久化對(duì)象本身即可。
嵌入式表單:(Embedded Forms)
通常,你可能想生成一個(gè)表單,它包含來(lái)自不同對(duì)象的字段。比如,一個(gè)注冊(cè)表單可能包含屬于User對(duì)象和Address對(duì)象的字段。幸運(yùn)的是,這些對(duì)于form組件來(lái)說(shuō)都是很容易很自然的事。嵌入一個(gè)單獨(dú)對(duì)象:假設(shè)每個(gè)Task屬于一個(gè)Category對(duì)象,首先創(chuàng)建這個(gè)Category對(duì)象:
// src/Acme/TaskBundle/Entity/Category.php namespace Acme\TaskBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Category { /** * @Assert\NotBlank() */ public $name; }
接下來(lái),添加一個(gè)新的category屬性到Task類:
// ... class Task { // ... /** * @Assert\Type(type="Acme\TaskBundle\Entity\Category") */ protected $category; // ... public function getCategory() { return $this->category; } public function setCategory(Category $category = null) { $this->category = $category; } }
現(xiàn)在我們來(lái)相應(yīng)我們應(yīng)用程序的一個(gè)新需求,需要?jiǎng)?chuàng)建一個(gè) 表單可以讓用戶修改Category對(duì)象。
// src/Acme/TaskBundle/Form/Type/CategoryType.php namespace Acme\TaskBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; class CategoryType extends AbstractType { public function buildForm(FormBuilder $builder, array $options) { $builder->add('name'); } public function getDefaultOptions(array $options) { return array( 'data_class' => 'Acme\TaskBundle\Entity\Category', ); } public function getName() { return 'category'; } }
我們的最終目的是能夠讓用戶在Task表單中修改Category對(duì)象,所以,我們需要添加一個(gè)類型為CategoryType表單類的category字段到TaskType 表單類。
public function buildForm(FormBuilder $builder, array $options) { // ... $builder->add('category', new CategoryType()); }
這時(shí)我們可以在TaskType類字段渲染的旁邊渲染CategoryType類的字段了:
Twig格式:
{# ... #} <h3>Category</h3> <p class="category"> {{ form_row(form.category.name) }} </p> {{ form_rest(form) }} {# ... #}
PHP代碼格式:
<!-- ... --> <h3>Category</h3> <p class="category"> <?php echo $view['form']->row($form['category']['name']) ?> </p> <?php echo $view['form']->rest($form) ?> <!-- ... -->
當(dāng)用戶提交表單時(shí),提交的Category字段數(shù)據(jù)被用于創(chuàng)建一個(gè)Category實(shí)例,然后被設(shè)置到Task實(shí)例的category字段。該Category實(shí)例可以通過(guò)Task實(shí)例來(lái)訪問(wèn),同時(shí)也能被持久化到數(shù)據(jù)或者用作它用。
$task->getCategory()
嵌入一個(gè)表單集合
你也可以將一個(gè)表單集合嵌入到一個(gè)表單(想象一個(gè)Category 表單和許多Product子表單)。它是通過(guò)一個(gè)字段類型集合類實(shí)現(xiàn)的。
表單主題化
表單的每一部分渲染都是可以被自定義個(gè)性化的。你可以自由的改變每一個(gè)表單行的渲染,改變渲染錯(cuò)誤的標(biāo)志,更或者是textarea標(biāo)簽應(yīng)該怎樣顯示等。沒(méi)有任何限制,不同的個(gè)性化設(shè)置能用到不同的區(qū)域。
Symfony使用模板渲染每一個(gè)或者部分表單,比如label標(biāo)簽,input標(biāo)簽,錯(cuò)誤信息以及任何其它內(nèi)容。在Twig中,每個(gè)表單片段會(huì)被一個(gè)Twig block來(lái)渲染。要個(gè)性化渲染表單,你只需要重寫(xiě)相應(yīng)的block即可。在PHP模板中,它是通過(guò)單獨(dú)的模板文件來(lái)渲染表單片段的,所以你需要通過(guò)編寫(xiě)新的模板來(lái)替代舊的模板即可。在理解了它們是怎么工作的之后,讓我們來(lái)個(gè)性化form_row片段并添加一個(gè)class屬性到包裹每一表單行的p元素。首先創(chuàng)建一個(gè)新模板文件用于存放新的標(biāo)志:
Twig格式:
{# src/Acme/TaskBundle/Resources/views/Form/fields.html.twig #} {% block field_row %} {% spaceless %} <p class="form_row"> {{ form_label(form) }} {{ form_errors(form) }} {{ form_widget(form) }} </p> {% endspaceless %} {% endblock field_row %}
PHP代碼格式:
<!-- src/Acme/TaskBundle/Resources/views/Form/field_row.html.php --> <p class="form_row"> <?php echo $view['form']->label($form, $label) ?> <?php echo $view['form']->errors($form) ?> <?php echo $view['form']->widget($form, $parameters) ?> </p>
field_row表單片段會(huì)在通過(guò)form_row函數(shù)渲染大部分的表單字段時(shí)使用。 要告訴你的表單組件使用你的新的field_row片段,需要添加下面的內(nèi)容到你渲染該表單的模板頂部:
Twig格式:
{# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #} {% form_theme form 'AcmeTaskBundle:Form:fields.html.twig' %} {% form_theme form 'AcmeTaskBundle:Form:fields.html.twig' 'AcmeTaskBundle:Form:fields2.html.twig' %} <form ...>
PHP代碼格式:
<!-- src/Acme/TaskBundle/Resources/views/Default/new.html.php --> <?php $view['form']->setTheme($form, array('AcmeTaskBundle:Form')) ?> <?php $view['form']->setTheme($form, array('AcmeTaskBundle:Form', 'AcmeTaskBundle:Form')) ?> <form ...>
其中的form_theme 標(biāo)簽導(dǎo)入前面定義的片段。換句話說(shuō),當(dāng)form_row函數(shù)在模板中被調(diào)用后,它將從你的自定義主題中使用field_row 塊(替代Symfony已有的field_row block)。你的個(gè)性化主題不必重寫(xiě)所有的塊。當(dāng)渲染一個(gè)你沒(méi)有重寫(xiě)過(guò)的塊時(shí),主題引起會(huì)找全局的主題(定義在bundle級(jí)的主題)使用。
在擁有多個(gè)個(gè)性化主題的情況下,它會(huì)在使用全局主題之前查找定制列表。要個(gè)性化你表單的任何部分,你只需要重寫(xiě)相關(guān)的片段即可。
表單片段命名
在symfony中,表單的每一部分都會(huì)被渲染,HTML表單元素,錯(cuò)誤消息,顯示標(biāo)簽等這些都是被定義在基礎(chǔ)主題里的。它組成了一個(gè)Twig的塊集合和一個(gè)PHP模板集合。
在Twig中,每個(gè)需要的塊都被定義到一個(gè)單獨(dú)的模板文件中(form_pe_layout.html.twig),它們被保存在Twig Bridge里。在這個(gè)文件中,你可以看到渲染一個(gè)表單多需要的每一個(gè)block和默認(rèn)的字段類型。
在PHP模板中,片段是單獨(dú)的模板文件。 默認(rèn)情況下它們位于框架bundle的Resources/views/Form 目錄下。每個(gè)偏度名稱都遵循相同的基本模式,用一個(gè)下劃線(_)分為兩部分,比如:
field_row 用于form_row渲染大部分的字段
textarea_widget 用于form_widget渲染一個(gè)textarea字段類型
field_errors 用于form_errors渲染一個(gè)字段的錯(cuò)誤信息
每個(gè)片段都命名都遵循:type_part 模式。type部分對(duì)應(yīng)被渲染的字段類型(比如textarea,checkbox,date等),而part部分對(duì)應(yīng)著是什么被渲染(比如label,widget,errors等)
默認(rèn)情況下,有4種可能的表單part被用來(lái)渲染:
label 渲染字段的標(biāo)簽 如field_label
widget 渲染字段的HTML表示 如field_widget
errors 渲染字段的錯(cuò)誤信息 如field_errors
row 渲染字段的整個(gè)行(包括label,widget和errors) 如 filed_row
還有其它3個(gè)part類型,分別是rows,rest和enctype,不過(guò)這三個(gè)一般不會(huì)用到。
通過(guò)知道字段類型(比如:textarea)和你想渲染那一部分(比如:widget),你可以創(chuàng)建一個(gè)你需要重寫(xiě)的片段名稱(比如:textarea_widget).
模板片段繼承
在某些情況下,你個(gè)性化的片段可能會(huì)丟失。比如,在Symfony提供的默認(rèn)主題中沒(méi)有提供textarea_errors片段。那么如何來(lái)渲染一個(gè)textarea字段的錯(cuò)誤信息呢?
答案是通過(guò)field_errors片段。當(dāng)Symfony渲染一個(gè)textarea類型的錯(cuò)誤時(shí),它首先查找一個(gè)textarea_errors片段,如果沒(méi)有找到則會(huì)回到field_errors片段。
每個(gè)field類型有一個(gè)parenttype(textarea的父類型為field),Symfony如果沒(méi)有發(fā)現(xiàn)本身的片段,就會(huì)轉(zhuǎn)而使用父類片段。
所以,要重寫(xiě)textarea字段的errors,拷貝field_errors片段,重命名為textarea_errors并個(gè)性化它們。為所有字段重寫(xiě)默認(rèn)的error渲染,則需要直接拷貝和個(gè)性化field_errors片段。
全局表單主題
在上面的示例中,我們使用了form_theme helper來(lái)導(dǎo)入自定義個(gè)的表單片段到表單。你也可以告訴Symfony在全項(xiàng)目中導(dǎo)入自定義的form。
Twig
為了從所有之前創(chuàng)建的fileds.html.twig模板中自動(dòng)包含個(gè)性化的block,修改你的應(yīng)用程序配置文件:
YAML格式:
# app/config/config.yml twig: form: resources: - 'AcmeTaskBundle:Form:fields.html.twig' # ...
XML格式:
<!-- app/config/config.xml --> <twig:config ...> <twig:form> <resource>AcmeTaskBundle:Form:fields.html.twig</resource> </twig:form> <!-- ... --> </twig:config>
PHP代碼格式:
// app/config/config.php $container->loadFromExtension('twig', array( 'form' => array('resources' => array( 'AcmeTaskBundle:Form:fields.html.twig', )) // ... ));
現(xiàn)在在fields.html.twig模板中的任何塊都可以被廣泛的使用來(lái)定義表單輸出了。
自定義表單輸出到一個(gè)單一的Twig文件中
在Twig中,你也可以個(gè)性化一個(gè)表單塊在模板中
{% extends '::base.html.twig'%} {# 導(dǎo)入"_self" 作為一個(gè)表單主題 #} {% form_theme form _self %} {# 個(gè)性化表單片段 #} {% block field_row %} {# 自定義字段行輸出 #} {% endblock field_row %} {% block content %} {# ... #} {{ form_row(form.task) }} {% endblock %}
這里{% form_theme form _self %}標(biāo)簽允許表單塊在使用那些自動(dòng)化內(nèi)容的模板中被直接自定義化。使用這個(gè)方法來(lái)快速的生成個(gè)性化輸出。
注意,{% form_theme form _self %}的功能只有在繼承自其它模板時(shí)才能起作用,如果不是繼承自其它模板,則需要指出form_theme 到單獨(dú)模板中。
PHP
從以前在所有模板中創(chuàng)建的Acme/TaskBundle/Resources/views/Form 目錄自動(dòng)導(dǎo)入個(gè)性化模板。修改你的配置文件:
YAML格式:
# app/config/config.yml framework: templating: form: resources: - 'AcmeTaskBundle:Form' # ...
XML格式:
<!-- app/config/config.xml --> <framework:config ...> <framework:templating> <framework:form> <resource>AcmeTaskBundle:Form</resource> </framework:form> </framework:templating> <!-- ... --> </framework:config>
PHP代碼格式:
// app/config/config.php $container->loadFromExtension('framework', array( 'templating' => array('form' => array('resources' => array( 'AcmeTaskBundle:Form', ))) // ... ));
此時(shí)在Acme/TaskBundle/Resources/views/Form目錄中的任何片段都可以全局范圍內(nèi)定義表單輸出了。
CSRF 保護(hù)
CSRF--Cross-site request forgery,跨站偽造請(qǐng)求 是惡意攻擊者試圖讓你的合法用戶在不知不覺(jué)中提交他們本不想提交的數(shù)據(jù)的一種方法。
幸運(yùn)的是,CSRF攻擊可以通過(guò)在你的表單中使用CSRF 記號(hào)來(lái)阻止。
默認(rèn)情況下,Symfony自動(dòng)為你嵌入一個(gè)合法的CSRF令牌。這就意味著你不需要做任何事情就可以得到CSRF保護(hù)。CSRF保護(hù)是通過(guò)在你的表單中添加一個(gè)隱藏字段,默認(rèn)的名叫_token。它包含一個(gè)值,這個(gè)值只有你和你的用戶知道。這確保了是用戶而不是其它實(shí)體在提交數(shù)據(jù)。Symfony自動(dòng)校驗(yàn)該token是否存在以及其準(zhǔn)確性。
_token 字段是一個(gè)隱藏字段并且會(huì)自動(dòng)的渲染,只要你在你的模板中包含了form_rest()函數(shù)。它確保了沒(méi)有被渲染過(guò)的字段全部渲染出來(lái)。CSRF令牌可以按照表單來(lái)個(gè)性化,比如:
class TaskType extends AbstractType { // ... public function getDefaultOptions(array $options) { return array( 'data_class' => 'Acme\TaskBundle\Entity\Task', 'csrf_protection' => true, 'csrf_field_name' => '_token', // 一個(gè)唯一的鍵值來(lái)保證生成令牌 'intention' => 'task_item', ); } // ... }
要關(guān)閉CSRF保護(hù),設(shè)置csrf_protection 選項(xiàng)為false。intentsion選項(xiàng)是可選的,但為不同的表單生成不同的令牌極大的加強(qiáng)了安全性。
使用一個(gè)無(wú)底層類表單
大多數(shù)情況下,一個(gè)表單要綁定一個(gè)對(duì)象的,并且表單中所有的字段獲取或者保存它們的數(shù)據(jù)到該對(duì)象屬性。但有時(shí)候,你可能只想使用一個(gè)沒(méi)有類的表單,返回一個(gè)提交數(shù)據(jù)的數(shù)組,這個(gè)非常容易實(shí)現(xiàn):
// 確認(rèn)你在類上方導(dǎo)入了Request對(duì)象 use Symfony\Component\HttpFoundation\Request // ... public function contactAction(Request $request) { $defaultData = array('message' => 'Type your message here'); $form = $this->createFormBuilder($defaultData) ->add('name', 'text') ->add('email', 'email') ->add('message', 'textarea') ->getForm(); if ($request->getMethod() == 'POST') { $form->bindRequest($request); // 數(shù)據(jù)是一個(gè)數(shù)組并包含 "name", "email", 和"message" 鍵 $data = $form->getData(); } // ... 渲染表單 }
默認(rèn)情況下,一個(gè)表單真的假設(shè)你想要一個(gè)數(shù)據(jù)數(shù)組而不是數(shù)據(jù)對(duì)象。
這里有兩種方式你可以改變它的行為并綁定一個(gè)對(duì)象;
1.當(dāng)創(chuàng)建表單時(shí)傳入一個(gè)對(duì)象(作為createFormBuilder的第一個(gè)參數(shù)或者createForm的第二個(gè)參數(shù))。
2.在你的表單中聲明data_class 選項(xiàng)
如果以上兩種方式都沒(méi)有,那么表單會(huì)返回一個(gè)數(shù)組數(shù)據(jù)。在這個(gè)示例中因?yàn)?defaultData不是一個(gè)對(duì)象,又沒(méi)有設(shè)置data_class選項(xiàng),則$form->getData()最終返回一個(gè)數(shù)組。
你也可以通過(guò)Request對(duì)象直接訪問(wèn)POST的值,
$this->get('request')->request->get('name');
注意,大多數(shù)的情況下我們使用getData()方法是更好一點(diǎn)的選擇。因?yàn)樗祷氐氖墙?jīng)過(guò)表單框架轉(zhuǎn)換過(guò)的數(shù)據(jù)。
添加校驗(yàn)規(guī)則
唯一遺漏的地方就是校驗(yàn)規(guī)則了,通常當(dāng)你調(diào)用$form->isvalid()時(shí),對(duì)象會(huì)調(diào)用你在類東提供的校驗(yàn)規(guī)則進(jìn)行校驗(yàn)。但如果沒(méi)有類,你怎么來(lái)添加對(duì)你表單數(shù)據(jù)的約束規(guī)則呢?答案是自己創(chuàng)建約束,然后傳入到表單。
// 在controller類前導(dǎo)入命名空間 use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Constraints\MinLength; use Symfony\Component\Validator\Constraints\Collection; $collectionConstraint = new Collection(array( 'name' => new MinLength(5), 'email' => new Email(array('message' => 'Invalid email address')), )); // 創(chuàng)建一個(gè)表單沒(méi)有默認(rèn)值,傳入約束選項(xiàng)。 $form = $this->createFormBuilder(null, array( 'validation_constraint' => $collectionConstraint, ))->add('email', 'email') // ... ;
現(xiàn)在,當(dāng)你調(diào)用$form->bindRequest($request)時(shí),約束就會(huì)被創(chuàng)建并作用于你的表單數(shù)據(jù)。如果你使用表單類,重寫(xiě)getDefaultOptions 方法來(lái)指定可選項(xiàng):
namespace Acme\TaskBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Constraints\MinLength; use Symfony\Component\Validator\Constraints\Collection; class ContactType extends AbstractType { // ... public function getDefaultOptions(array $options) { $collectionConstraint = new Collection(array( 'name' => new MinLength(5), 'email' => new Email(array('message' => 'Invalid email address')), )); return array('validation_constraint' => $collectionConstraint); } }
這樣你有了足夠的靈活性來(lái)創(chuàng)建表單類和約束了,它返回一個(gè)數(shù)據(jù)數(shù)組而不是一個(gè)對(duì)象。大多數(shù)情況下,這個(gè)是不錯(cuò)的,而綁定一個(gè)表單到一個(gè)對(duì)象,從某種程度上說(shuō)更加健壯。對(duì)于簡(jiǎn)單表單來(lái)說(shuō)是個(gè)不錯(cuò)的選擇。
總結(jié)思考
你現(xiàn)在已經(jīng)了解了所有建造復(fù)雜功能性的表單所需要的所有建造塊。當(dāng)生成表單時(shí),記住一個(gè)表單的首要目標(biāo)是從一個(gè)對(duì)象把數(shù)據(jù)傳遞給一個(gè)HTML表單以方便用戶修改它們。第二個(gè)目標(biāo)就是把用戶提交的數(shù)據(jù)重寫(xiě)提交回對(duì)象。
Atas ialah kandungan terperinci 詳解Symfony2框架表單的用法. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Klasifikasi dan Analisis Penggunaan Komen JSP Komen JSP terbahagi kepada dua jenis: komen satu baris: berakhir dengan, hanya satu baris kod boleh diulas. Komen berbilang baris: bermula dengan /* dan berakhir dengan */, anda boleh mengulas berbilang baris kod. Contoh ulasan satu baris Contoh ulasan berbilang baris/**Ini ialah ulasan berbilang baris*Boleh mengulas pada berbilang baris kod*/Penggunaan ulasan JSP Komen JSP boleh digunakan untuk mengulas kod JSP agar lebih mudah dibaca

Bagaimana untuk menggunakan JavaScript untuk merealisasikan fungsi gesaan automatik kandungan kotak input borang? Pengenalan: Fungsi gesaan automatik kandungan kotak input borang adalah sangat biasa dalam aplikasi web Ia boleh membantu pengguna memasukkan kandungan yang betul dengan cepat. Artikel ini akan memperkenalkan cara menggunakan JavaScript untuk mencapai fungsi ini dan menyediakan contoh kod khusus. Cipta struktur HTML Mula-mula, kita perlu mencipta struktur HTML yang mengandungi kotak input dan senarai cadangan automatik. Anda boleh menggunakan kod berikut: <!DOCTYP

Pengenalan kepada fungsi Python: penggunaan dan contoh fungsi abs 1. Pengenalan kepada penggunaan fungsi abs Dalam Python, fungsi abs ialah fungsi terbina dalam yang digunakan untuk mengira nilai mutlak nilai tertentu. Ia boleh menerima hujah berangka dan mengembalikan nilai mutlak nombor itu. Sintaks asas fungsi abs adalah seperti berikut: abs(x) dengan x ialah parameter berangka untuk mengira nilai mutlak, yang boleh menjadi integer atau nombor titik terapung. 2. Contoh fungsi abs Di bawah kami akan menunjukkan penggunaan fungsi abs melalui beberapa contoh khusus: Contoh 1: Pengiraan

Pengenalan kepada fungsi Python: Penggunaan dan contoh fungsi isinstance Python ialah bahasa pengaturcaraan berkuasa yang menyediakan banyak fungsi terbina dalam untuk menjadikan pengaturcaraan lebih mudah dan cekap. Salah satu fungsi terbina dalam yang sangat berguna ialah fungsi isinstance(). Artikel ini akan memperkenalkan penggunaan dan contoh fungsi isinstance dan memberikan contoh kod khusus. Fungsi isinstance() digunakan untuk menentukan sama ada objek ialah contoh kelas atau jenis tertentu. Sintaks fungsi ini adalah seperti berikut

Cara menggunakan fungsi keluar dalam bahasa C memerlukan contoh kod khusus Dalam bahasa C, kita selalunya perlu menamatkan pelaksanaan program pada awal program, atau keluar dari program dalam keadaan tertentu. Bahasa C menyediakan fungsi exit() untuk melaksanakan fungsi ini. Artikel ini akan memperkenalkan penggunaan fungsi exit() dan memberikan contoh kod yang sepadan. Fungsi exit() ialah fungsi perpustakaan standard dalam bahasa C dan disertakan dalam fail pengepala. Fungsinya adalah untuk menamatkan pelaksanaan program, dan boleh mengambil integer

WPS ialah suite perisian pejabat yang biasa digunakan, dan fungsi jadual WPS digunakan secara meluas untuk pemprosesan dan pengiraan data. Dalam jadual WPS, terdapat fungsi yang sangat berguna, fungsi DATEDIF, yang digunakan untuk mengira perbezaan masa antara dua tarikh. Fungsi DATEDIF ialah singkatan daripada perkataan Inggeris DateDifference Sintaksnya adalah seperti berikut: DATEDIF(start_date,end_date,unit) dengan start_date mewakili tarikh mula.

Bagaimana untuk menggunakan JavaScript untuk melaksanakan pengesahan masa nyata kandungan kotak input borang? Dalam kebanyakan aplikasi web, borang ialah cara interaksi yang paling biasa antara pengguna dan sistem. Walau bagaimanapun, kandungan yang dimasukkan oleh pengguna selalunya perlu disahkan untuk memastikan ketepatan dan kesempurnaan data. Dalam artikel ini, kami akan mempelajari cara menggunakan JavaScript untuk melaksanakan pengesahan masa nyata kandungan kotak input borang dan memberikan contoh kod khusus. Mencipta borang Mula-mula kita perlu mencipta jadual ringkas dalam HTML

Cara menggunakan HTML, CSS dan jQuery untuk melaksanakan fungsi lanjutan untuk menyimpan borang secara automatik adalah salah satu elemen yang paling biasa dalam aplikasi web moden. Apabila pengguna memasukkan data borang, bagaimana untuk melaksanakan fungsi penjimatan automatik bukan sahaja dapat meningkatkan pengalaman pengguna, tetapi juga memastikan keselamatan data. Artikel ini akan memperkenalkan cara menggunakan HTML, CSS dan jQuery untuk melaksanakan fungsi penjimatan automatik borang, dan melampirkan contoh kod tertentu. 1. Struktur bentuk HTML Mari kita buat satu bentuk HTML yang mudah.
