轉自:http://blog.sina.com.cn/s/blog_5a8b8eb80100ra1l.html
表單屬性:
#access該布爾值屬性決定表單元素對于使用者是否可見。如果表單元素有子表單元素的話,如果父表單元素的#access屬性為FALSE的話,那麼子表單元素将不被顯示出來。例如,如果表單元素是一個字段集的話,如果它的#access為FALSE的話,那麼字段集裡面的所有的字段都不被顯示。
‘#access’=> FALSE, // 表單是否可見
'#collapsible' => TRUE, // 顯示為可折疊菜單
'#collapsed' => FALSE, //收縮狀态,false:折疊,true:展開
'#required' => TRUE, //必填項
'#default_value' => "F", //預設值
'#description' => "", //描述
'#size' => 20, //控件大小
'#maxlength' => 20, //可輸入文字的長度
Drupal提供了一個應用程式接口(API),用來生成、驗證和處理HTML表單。表單API将表單抽象為一個嵌套數組,裡面包含了屬性和值。在生成頁面時,表單呈現引擎會在适當的時候将數組呈現出來。這種方式包含多層含義:
我們沒有直接輸出HTML,而是建立了一個數組并讓引擎生成HTML。
由于我們将表單的表示作為結構化的資料進行處理,是以我們可以添加、删除、重新排序、和修改表單。當你想用一種幹淨利索的方式對其它子產品建立的表單進行修改時,這會特别友善。
任意的表單元素可以映射到任意的主題函數上。
可以将額外的表單驗證或處理函數添加到任意表單上。
對表單操作進行了保護,進而防止表單注入攻擊,比如當使用者修改了表單并接着試圖送出它時。
使用表單的學習曲線有點高.
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiInBnauETLwEzLcNjMwETOwAjMvwVZnFWbp9CXzVGbpZ2LcRHb1FmZlR2LcNXZ0l2cvwVbvNmLsFGc1JHZ3EjL3d3dvw1LcpDc0RHaiojIsJye.jpg)
了解表單處理流程:
Drupal的表單引擎負責為要顯示的表單生成HTML,并使用三個階段來安全的處理送出了的表單:驗證、送出、重定向。
流程初始化
在處理表單時,有3個變量非常重要。第一個就是$form_id,它包含了一個辨別表單的字元串。第二個就是$form,它是一個描述表單的結構化數組。 而第三個就是$form_state,它包含了表單的相關資訊,比如表單的值以及當表單處理完成時應該發生什麼。drupal_get_form()在開 始時,首先會初始化$form_state。
設定一個令牌(token)
表單系統的一個優點是,它盡力的去保證被送出的表單就是Drupal實際建立的,這主要是為了安全性和防止垃圾資訊或潛在的站點攻擊者。為了實作這一 點,Drupal為每個Drupal安裝都設定了一個私鑰。這個私鑰是在安裝流程期間随機生成的,它能将這個特定的Drupal安裝與其它的Drupal 差別開來。一旦私鑰生成後,它将作為drupal_private_key存儲在variables表中。Drupal将基于私鑰生成一個随機的令牌,而 該令牌将作為隐藏域發送到表單中。當表單送出時,會對令牌進行測試。相關背景資訊請參看drupal.org/node/28420。令牌僅用于登入用 戶,因為匿名使用者的頁面通常會被緩存起來,這樣它們就沒有唯一的令牌了。
設定一個ID
一個包含了目前表單ID的隐藏域,将作為表單的一部分被發送給浏覽器。該ID一般對應于定義表單的函數,它将作為drupal_get_form()的第一個參數傳遞過來。例如函數user_register()定義了使用者系統資料庫單,它的調用方式如下:
$output = drupal_get_form('user_register');
收集所有可能的表單元素定義:
接着,調用element_info()。它将調用所有實作了hook_elements()的子產品上的這個鈎子函數。在Drupal核心中,标準的元 素,比如單選按鈕和複選框,都定義在modules/system/system.module中的hook_elements()實作中(參看 system_elements())。如果子產品需要定義它們自己的元素類型,那麼就需要實作這個鈎子。在以下幾種情況中,你可能需要在你的子產品中實作 hook_elements():你想要一個特殊類型的表單元素時,比如一個圖像上傳按鈕,在節點預覽期間可用來顯示縮略圖;或者,你想通過定義更多的屬 性來擴充已有的表單元素時。
鈎子element_info()為所有的表單元素收集所有的預設屬性,并将其儲存到一個本地緩存中。在進入下一步----為表單尋找一個驗證器----以前,對于那些在表單定義中尚未出現的任何預設屬性,都将在這裡被添加進來。
尋找一個驗證函數:
通過将表單的屬性#validate設定為一個數組,其中函數名為為值,進而為表單配置設定一個驗證函數。在調用驗證函數時,後面的數組中的任何資料都将被傳遞給驗證函數。可以使用下面的方式來定義多個驗證器:
// We want foo_validate() and bar_validate() to be called during form validation.
$form['#validate'][] = 'foo_validate';
$form['#validate'][] = 'bar_validate';
如果表單中沒有定義屬性#validate,那麼接下來就要尋找名為“表單ID”+“_validate”的函數。是以,如果表單ID為user_register,那麼表單的#validate屬性将被設定為user_register_validate。
尋找一個送出函數:
通過将表單的#submit屬性設定為一個數組,其中以函數名為鍵/值,這裡的函數名就是用來處理表單送出的函數的名字,進而為表單配置設定一個送出函數:
// Call my_special_submit_function() on form submission.
$form['#submit'][] = 'my_special_submit_function';
// Also call my_second_submit_function().
$form['#submit'][] = 'my_second_submit_function';
如果表單沒有名為#submit的屬性,那麼接下來就要尋找名為“表單ID”+“_submit”的函數。是以,如果表單ID為 user_register,那麼Drupal将把#submit屬性設定為它所找到的表單處理器函數;也就是 user_register_submit。
允許子產品在表單建構以前修改表單
在建構表單以前,子產品有兩個可以修改表單的機會。子產品可以實作一個名字源于form_id + _alter的函數,或者可以簡單的實作hook_form_alter()。任何子產品,隻要實作了這兩個鈎子中的任意一個,那麼就可以修改表單中的任何東西。對于由第3方子產品建立的表單,我們主要可以使用這種方式對其進行修改、覆寫、混合。
建構表單
現在表單被傳遞給了form_builder(),這個函數将對表單樹進行遞歸處理,并為其添加标準的必須值。這個函數還将檢查每個元素的#access鍵,如果該元素的#access為FALSE,那麼将拒絕對該表單元素及其子元素的通路。
允許函數在表單建構後修改表單
函數form_builder()每次遇到$form樹中的一個新分支時(例如,一個新的字段集或表單元素),它都尋找一個名為#after_build 的可選屬性。這是一個可選的數組,裡面包含了目前表單元素被建構後會立即調用的函數。當整個表單被建構後,最後将調用可選屬性$form[‘#after_build’] 中定義的函數。$form和$form_state将作為參數傳遞給所有的#after_build函數。Drupal核心中有一個實際例子,那就是在 “管理➤站點配置➤檔案系統”中,檔案系統路徑的顯示。這裡使用了一個#after_build函數(在這裡就是 system_check_directory()),用來判定目錄是否存在或者是否可寫,如果不存在或不可寫,那麼将為該表單元素設定一個錯誤消息。
檢查表單是否已被送出
如果你是按照流程往下走的話,那麼你将看到我們現在來到了一個分叉點。如果表單是初次顯示的話,那麼Drupal将會為其建立HTML。如果表單正被送出 的話,那麼Drupal将處理在表單中所輸入的資料;我們稍後将會讨論這一點(參看後面的“驗證表單”一節)。現在,我們将假定表單是初次顯示。有一點非 常重要,那就是不管表單是初次顯示,還是正被送出,在此以前,它所走過的流程是一樣的。
為表單查找一個主題函數
如果$form['#theme']已被設定為了一個已有函數,那麼Drupal将簡單的使用該函數來負責表單的主題化。如果沒有設定,那麼主題系統資料庫将 查找一個對應于這個表單的表單ID的條目。如果存在這樣的一個條目,那麼就會将表單ID配置設定給$form['#theme'],在後面,當Drupal呈 現表單時,它将基于表單ID來尋找主題函數。例如,如果表單ID為taxonomy_overview_terms,那麼Drupal将調用對應的主題函 數theme_taxonomy_overview_terms()。當然,可以在自定義主題中,使用主題函數或者模闆檔案來覆寫這個主題函數。
允許子產品在表單呈現以前修改表單
最後剩下的一件事,就是将表單從結構化的資料轉化為HTML。但是在這以前,子產品還有最後一個機會來調整表單。對于跨頁面表單向導,或者需要在最後時刻修 改表單的其它方式,這将會非常有用。此時将會調用$form['#pre_render']屬性定義的任何函數,并将正被呈現的表單傳遞給這些函數。
呈現表單:
為了将表單樹從一個嵌套數組轉化為HTML代碼,表單建構器調用drupal_render()。這個遞歸函數将會周遊表單樹的每個層次,對于每個層次,它将執行以下動作:
1. 判定是否定義了#children屬性(這句話就是說,是否已經為該元素生成内容了);如果沒有,那麼按照以下步驟來呈現這個樹節點的孩子:
• 判定是否為這個元素定義了一個#theme函數。
• 如果定義了,那麼将這個元素的#type臨時設定為markup(辨別字型)。接着,将這個元素傳遞給主題函數,并将該元素重置為原來的樣子。
• 如果沒有生成内容(可能是因為沒有為這個元素定義#theme函數,或者因為調用的#theme函數在主題系統資料庫中不存在,或者因為調用的#theme函數沒有傳回東西),那麼逐個呈現這個元素的子元素(也就是,将子元素傳遞給drupal_render())。
• 另一方面,如果#theme函數生成了内容,那麼将内容存儲在這個元素的#children屬性中。
2. 如果表單元素本身還沒有被呈現出來,那麼調用這個元素所屬類型的預設主題函數。例如,如果這個元素是表單中的一個文本字段(也就是說,在表單定義中,它 的#type屬性被設定為了textfield),那麼預設主題函數就是theme_textfield()。如果沒有為這個元素設定#type屬性,那 麼預設為markup。核心元素(比如文本字段)的預設主題函數位于includes/form.inc中。
3. 如果為這個元素生成了内容,并且在#post_render屬性中找到了一個或多個函數名字,那麼将分别調用這些函數,并将内容和該元素傳遞過去。
4. 在内容前面添#prefix,在後面追加#suffix,并将它從函數中傳回。
這個遞歸疊代的作用就是為表單樹的每個層次生成HTML。例如,一個表單了包含一個字段集,而字段集裡面又包含兩個字段,那麼該字段集 的#children屬性将包含兩個字段的HTML,而表單的#children屬性将包含整個表單的HTML(其中包括字段集的HTML)。
生成的HTML将會傳回給drupal_get_form()的調用者。這就是呈現表單所要做的全部工作!我們到達了流程中中的終點“傳回HTML”。
驗證表單:
我們在“檢查表單是否已被送出”一節中所提到的分叉點。現在讓我們假定表單已被送出并包含了一些資料;這樣我們将沿着另一分支前進,看看這種情況是怎麼樣 的。使用以下兩點來判定一個表單已被送出:$_POST不為空,$_POST['form_id']中的字元串比對剛被建構的表單定義中的ID。如果這兩 點都滿足了,那麼Drupal 将開始驗證表單。
驗證的目的是為了檢查證被送出的資料的合理性。驗證或者通過,或者失敗。如果驗證在某一點上失敗了,那麼将為使用者重新顯示這個表單,并帶有錯誤消息。如果所有的驗證都通過了,那麼Drupal将對送出的資料進行實際的處理。
令牌驗證
在驗證中首先檢查的是,該表單是否使用了Drupal的令牌機制。使用令牌的所有Drupal表單,都會有一個唯一的令牌,它和表單一起被發送給浏覽器, 并且應該和其它表單值一同被送出。如果送出的資料中的令牌與表單建構時設定的令牌不比對,或者令牌不存在,那麼驗證将會失敗(盡管驗證的其餘部分也會繼續 執行,這樣其它驗證錯誤也會被辨別出來)。
内置驗證
接着,檢查必填字段,看使用者有沒有漏填的。檢查帶有#maxlength屬性的字段,確定它沒有超過最大字元數。檢查帶有選項的元素(複選框、單選按鈕、下拉選擇框),看所選的值是否是位于建構表單時所生成的原始選項清單中。
特定元素的驗證
如果為單個表單元素定義了一個#validate屬性,那麼将會調用這個屬性所定義的函數,并将$form_state和$element作為參數傳遞過去。
驗證回調
最後,表單ID和表單值将被傳遞到表單的驗證器函數中(函數名一般為:“表單ID”+ “_validate”)。
送出表單:
如果驗證通過了,那麼現在就應該把表單和它的值傳遞到一個函數中,該函數将做些實際的處理,以作為表單送出的結果。實際上,由于#submit屬性可以包 含一個數組,裡面包含多個函數名字,是以可以使用多個函數來處理表單。調用數組中的每個函數,并向其傳遞參數$form和$form_state。
重定向:
用來處理表單的函數,應該把$form_state['redirect']設定為一個Drupal路徑,比如node/1234,這樣就可以将使用者重定 向到這個頁面了。如果#submit屬性中有多個函數,那麼将會使用最後一個函數設定的$form_state['redirect']。如果沒有函數 把$form_state['redirect']設定為一個Drupal路徑,那麼使用者将傳回原來的頁面(也就是,$_GET['q']的值)。在最後 一個送出函數中傳回FALSE,将會阻止重定向
通過在表單中定義#redirect屬性,就可以覆寫在送出函數中$form_state['redirect']設定的重定向了,比如
$form['#redirect'] = 'node/1'或$form['#redirect'] = array('node/1', $query_string, $named_anchor)
如果使用drupal_goto()中所用的參數術語,那麼最後的一個例子将被改寫為
$form['#redirect'] = array('node/1', $query, $fragment)
表單重定向的判定,是由includes/form.inc中的drupal_redirect_form()完成的。而實際的重定向則由drupal_goto()實作,它為Web伺服器傳回一個Location頭部。 drupal_goto()的參數與後一個例子中的參數一緻:drupal_goto($path = '', $query = NULL, $fragment = NULL)。
建立基本的表單: ....
表單屬性:
屬性和元素有哪些差別呢?最基本的差別就是,屬性沒有屬性,而元素可以有屬性。送出按鈕就是一個元素的例子,而送出按鈕的#type屬性就是一個屬性的例 子。你一眼便可以認出屬性,這是因為屬性擁有字首“#”。我們有時把屬性稱為鍵,因為它們擁有一個值,為了得到該值,你必須知道相應的鍵。一個初學者常見 的錯誤就是忘記了字首“#”,此時,無論是Drupal還是你自己,都會感到非常困惑。如果你看到了錯誤消息“Cannot use string offset as an array in form.inc”,那麼十有八九就是你忘記了字元“#”。
屬性是通用的,而有些則特定于一個元素,比如一個按鈕。 例:
$form['#method'] = 'post';
$form['#action'] = 'http://example.com/?q=foo/bar';
$form['#attributes'] = array(
'enctype' => 'multipart/form-data',
'target' => 'name_of_target_frame'
);
$form['#prefix'] = '<div class="my-form-class">';
$form['#suffix'] = '</div>';
#method屬性的預設值為post,它可以被忽略。表單API不支援get方法,該方法在Drupal中也不常用,這是因為通過Drupal的菜單路 由機制可以很容易的自動解析路徑中的參數。#action屬性定義在system_elements(),預設值為函數request_uri()的結 果。通常與顯示表單的URL相同。
表單IDs:
drupal_get_form()的調用中,所用的就是ID.對于大多數表單,其ID的命名規則為:子產品名字+一個表述該表單做什麼的辨別。
Drupal使用表單ID來決定表單的驗證、送出、主題函數的預設名字.另外,Drupal使用表單ID作為基礎來為該特定表單生成一個<form>标簽中的HTML ID屬性,這樣在Drupal中所有的表單都有一個唯一的ID。通過設定#id屬性,你可以覆寫該ID:
$form['#id'] = 'my-special-css-identifier';
生成的HTML标簽将會是這樣的:
<form action="/path" "accept-charset="UTF-8" method="post"
id="my-special-css-identifier">
字段集:
屬性#collapsible和#collapsed來使用Javascript讓它可以伸縮。
屬性#tree設為TRUE,你将得到一個嵌套的表單值數組。将屬性#tree設為FALSE(預設情況),你将得到一個未嵌套的表單值數組。
主題化表單:
使用主題函數:
主題化表單的最靈活的方式,就是為表單或者表單元素使用一個特定的主題函數。首先,Drupal需要知道我們的子產品将實作哪些主題函數。這可以通過 hook_theme()來完成。擁有我們自己的主題函數的好處是,我們可以按照我們的意願對變量$output進行解析、混合、添加等操作。
告訴Drupal使用哪個主題函數:
通過為一個表單聲明#theme屬性,你可以指令Drupal使用一個不比對“‘theme_’+表單ID名字”格式的主題函數:
// Now our form will be themed by the function
// theme_formexample_alternate_nameform().
$form['#theme'] = 'formexample_alternate_nameform';
或者,你也可以讓Drupal為一個表單元素使用一個專門的主題函數:
// Theme this fieldset element with theme_formexample_coloredfieldset().
$form['color'] = array(
'#title' => t('Color'),
'#type' => 'fieldset',
'#theme' => 'formexample_coloredfieldset'
);
注意,在前面的兩種情況中,你在#theme屬性中定義的函數必須是主題系統資料庫中注冊過的;也就是說,必須在一個hook_theme()實作中對其進行了聲明。
使用hook_forms()聲明驗證和送出函數:
你想讓許多不同的表單共用一個驗證或者送出函數。這叫做代碼複用,可以用hook_forms()将多個表單ID映射到驗證和送出函數上。在Drupal 取回表單時,它首先查找基于表單ID定義表單的函數(正因為這樣,在我們的代碼中,我們使用函數formexample_nameform())。如果找 不到該函數,它将觸發hook_forms(),該鈎子函數在所有的子產品中查找比對的表單ID以進行回調。
主題、驗證、送出函數的調用次序:
對于一個主題函數,假定你使用基于PHPTemplate的名為bluemarine的主題,并且你正在調用drupal_get_form('formexample_nameform')。然而,這還取決于你的hook_theme()實作。
首先,如果在表單定義中将$form['#theme']設定為了'foo':
1. themes/bluemarine/foo.tpl.php // Template file provided by theme.
2. formexample/foo.tpl.php // Template file provided by module.
3. bluemarine_foo() // Function provided theme.
4. phptemplate_foo() // Theme function provided by theme engine.
5. theme_foo() // 'theme_' plus the value of $form['#theme'].
然而,如果在表單定義中沒有設定$form['#theme']:
1. themes/bluemarine/formexample-nameform.tpl.php // Template provided by theme.
2. formexample/formexample-nameform.tpl.php // Template file provided by module.
3. bluemarine_formexample_nameform() // Theme function provided by theme.
4. phptemplate_formexample_nameform() // Theme function provided by theme engine.
5. theme_formexample_nameform() // 'theme_' plus the form ID.
在驗證期間,表單驗證器的設定次序如下:
1. A function defined by $form['#validate']
2. formexample_nameform_validate // Form ID plus 'validate'.
當需要查找處理表單送出的函數時,查找的次序如下:
1. A function defined by $form['#submit']
2. formexample_nameform_submit // Form ID plus 'submit'.
編寫一個驗證函數:
從驗證函數中傳遞資料:
如果你的驗證函數做了大量的處理,而你又想把結果儲存下來以供送出函數使用,那麼有兩種不同的方式。你可以使用form_set_value()或者使用$form_state。
針對表單元素的驗證:
一般情況下,一個表單使用一個驗證函數。但是也可以為單個表單元素設定一個驗證函數,這和整個表單的驗證函數一樣。為了實作這一點,我們需要将元素的屬 性#element_validate設定為一個數組,其中包含了驗證函數的名字。表單資料結構中該元素分支的一份完整拷貝,将被作為驗證函數的第一個參 數。在調用完所有表單元素的驗證函數以後,仍需調用表單驗證函數。提示 在你的表單元素未通過驗證,你希望為它顯示一條錯誤消息時,如果你知道表單元素的名字,那麼使用form_set_error(),如果你擁有表單元素本 身,那麼使用form_error()。後者對前者做了簡單封裝。
表單重新建構:
在驗證期間,你可能判定你沒有從使用者那裡擷取足夠的資訊。例如,你可能将表單數值放到一個文本分析引擎中進行檢查,然後判定這一内容很有可能是垃圾資訊。 最後,你想重新顯示表單(裡面包含使用者已輸入的值),不過這次添加了一個CAPTCHA,用來證明這個使用者不是一個機器人。通過在你的驗證函數中設 置$form_state['rebuild'],你就可以通知Drupal需要進行一次重構了.
編寫送出函數:
送出函數是表單通過驗證後負責實際的表單處理的函數。隻有在表單驗證完全通過,并且表單沒有被标記為重新建構時,它才會執行。送出函數通常需要修改$form_state['redirect']。 如果你有多個函數用來處理表單送出,隻有最後一個設定$form_state['redirect']的函數返才擁有最後的發言權。可以通過在表單中定義#redirect屬性來覆寫送出函數的重定向。通常使用hook_form_alter()來實作這一點。
使用hook_form_alter()修改表單:
使用drupal_execute()通過程式來送出表單:
drupal_execute($form_id, $form_state);
修改一個特定的表單:
如果有很多子產品來修改表單,而每個表單都傳遞給所有的hook_form_alter()實作.然而可以通過根據表單ID構造一個函數并調用它。
函數的名字是這樣構造的:modulename + 'form' + form ID + 'alter'
例如'formexample' + 'form' + 'user_login' + 'alter' 将生成 formexample_form_user_login_alter
添加到所有表單元素上的屬性:
當表單建構器使用表單定義建構表單時,它需要保證每一個表單元素都要有一些預設設定。這些預設值在includes/form.inc的函數_element_info()中設定,但是可以被hook_elements()中的表單元素定義所覆寫。
#description
該字元串屬性将添加到所有表單元素上,預設為NULL。通過表單元素的主題函數來呈現它。例如,一個文本字段的描述呈現在textfield的下面。
#required
該布爾值屬性将被添加到所有表單元素上,預設為FALSE。将它設為TRUE,如果表單被送出以後而字段未被完成時,Drupal内置的表單驗證将抛出一 個錯誤消息。還有,如果将它設為TRUE,那麼就會為這個元素設定一個CSS類(參看includes/form.inc中的 theme_form_element())
#tree
該布爾值屬性将被添加到所有表單元素上,預設為FALSE。如果将它設為TRUE,表單送出後的$form_state['values']數組将會是嵌套的(而不是平坦的)。這将影響你通路送出資料的方式。(參看本章中的“字段集”部分)。
#post
該數組屬性是原始$_POST資料的一個拷貝,它将被表單建構器添加到所有的表單元素上。這樣,在#process 和 #after_build中定義的函數就可以基于#post的内容做出聰明的決定。
#parents
該數組屬性将被添加到所有表單元素上,預設為一個空數組。它在表單建構器的内部使用,以辨別表單樹中的父元素。更多資訊,參看http://drupal.org/node/48643。
#attributes
該數組屬性将被添加到所有表單元素上,預設為一個空數組,但是主題函數一般會填充該數組。該數組中的成員将被作為HTML屬性添加進來。例如$form['#attributes'] = array('enctype' => 'multipart/form-data')。
表單API屬性:
當在你的表單建構函數中建構一個表單定義時,數組中的鍵用來聲明表單的資訊。在下面部分中列出了最常用的鍵。表單建構器可以自動添加一些鍵。
表單根部的屬性
下面所列的屬性是特定于表單根部的。換句話說,你可以設定$form['#programmed'] = TRUE,但是如果你設定$form['myfieldset']['mytextfield'] [#programmed'] = TRUE那麼對表單建構器來說沒有任何意義。
#parameters
該屬性是一個數組,包含了傳遞給drupal_get_form()的原始參數。通過drupal_retrieve_form()可添加該屬性。
#programmed
這是一個布爾值屬性,用來訓示一個表單是以程式的方式來送出的, 比如通過drupal_execute()。如果在表單處理前設定了屬性#post,那麼可以使用drupal_prepare_form()來設定該屬性。
#build_id
該屬性是一個字元串(MD5哈希)。#build_id用來辨別一個特定的表單執行個體。它作為一個隐藏域放在表單中,通過使用drupal_prepare_form()來設定這個表單元素,如下所示:
$form['form_build_id'] = array(
'#type' => 'hidden',
'#value' => $form['#build_id'],
'#id' => $form['#build_id'],
'#name' => 'form_build_id',
);
#token
這個字元串(MD5哈希)是一個唯一的令牌,每個表單中都帶有它,通過該令牌Drupal能夠判定一個表單是一個實際的Drupal表單,而不是一個惡意使用者修改後的。
#id
這個屬性是一個由form_clean_id($form_id)生成的字元串,并且它是一個HTML ID屬性。$form_id中的任何背對的括号對“][”,下劃線“_”,或者空格’’都将被連字元替換,以生成一緻的CSS ID。在Drupal的同一個頁面中,該ID是唯一的.如果同一個ID出現兩次(例如,同一個表單在一個頁面顯示了兩次),那麼就會在後面添加一個連字元和一個自增的整數,例如foo-form, foo-form-1, 和foo-form-2。
#action
這個字元串屬性是HTML表單标簽的動作屬性。預設情況,它是request_uri()的傳回值。
#method
這個字元串屬性指的是表單的送出方法---通常為post。表單API是基于post方法建構的,它将不會處理使用GET方法送出的表單。關于GET 和POST的差別,可參看HTML規範。如果在某種情況下,你想嘗試使用GET方法,那麼你真正需要可能是Drupal的菜單API,而不是表單API。
#redirect
該屬性可以是一個字元串或者一個數組。如果是一個字元串,那麼它是在表單送出以後使用者想要重定向到的Drupal路徑。如果是一個數組,該數組将作為參數 被傳遞給drupal_goto(),其中數組中的第一個元素應該是目标路徑(這将允許向drupal_goto()傳遞額外的參數,比如一個查詢字元 串)。
#pre_render
該屬性是一個數組,它包含了在表單呈現以前所要調用的函數。每個函數都被調用,并且#pre_render所在的元素将被作為參數傳遞過來。例如,設 置$form['#pre_render'] = array('foo', 'bar') 将使Drupal先調用函數foo(&$form),然後調用bar(&$form)。如果#pre_render是設定在一個表單元素 上的話,比如$form['mytextfield']['#pre_render'] = array('foo'),那麼Drupal将調用foo(&$element),其中$element就 是$form['mytextfield']。當你想在表單驗證運作以後,呈現以前,使用鈎子修改表單結構時,這個屬性非常有用。如果想在驗證以前修改表 單,那麼使用hook_form_alter()。
#post_render
該屬性是一個數組,它包含了一組函數,這些函數可對剛被呈現的内容進行修改。如果你設定了$form['mytextfield']['#post_render'] = array('bar'),那麼你可以這樣修改剛建立的内容:
function bar($content, $element) {
$new_content = t('This element (ID %id) has the following content:',
array('%id' => $element['#id'])) . $content;
return $new_content;
}
#cache
該屬性控制着表單是否可被Drupal的一般緩存系統所緩存。對表單進行緩存意味着,在表單被送出時,它不需要再被重新建構。如果你想每次都重新建構表單的話,那麼你可以設定$form['#cache'] = FALSE。
表單元素:
Textfield(文本字段)
Password(密碼)
Password with Confirmation(帶确認的密碼)
Textarea(文本域)
Select(下拉選擇框)
Radio Buttons(單選按鈕)
Check Boxes(複選框)
Value(值)
Hidden(隐藏域)
Date(日期)
Weight(重量)
File Upload(檔案上傳)
Fieldset(字段集)
Submit(送出按鈕)
Button(按鈕)
Image Button(圖檔按鈕)
Markup(辨別文本)
Item(項目)
#ahah屬性
跨頁面表單:
通用的表單元素屬性:
#type
該字元串聲明了一個表單元素的類型。例如,#type = 'textfield'。表單根部必須包含聲明#type = 'form'。
#access
該布爾值屬性用來判定是否将該表單元素顯示給使用者。如果表單元素有子表單元素的話,如果父表單元素的#access屬性為FALSE的話,那麼子表單元素将不顯示。例如,如果表單元素是一個字段集,并且它的#access為FALSE,那麼字段集裡面的所有字段都不顯示。
#access屬性可被直接設定為TRUE或FALSE,也可以設定為執行時傳回TRUE或FALSE的函數。當表單定義被取回時,将會執行該函數。下面這個例子來自于Drupal的預設節點表單:
$form['revision_information']['revision'] = array(
'#access' => user_access('administer nodes'),
'#type' => 'checkbox',
'#title' => t('Create new revision'),
'#default_value' => $node->revision,
);
#process
該屬性是一個關聯數組。在數組的每個條目中,函數名作為鍵,傳遞給函數的任何參數作為值。當建構表單元素時将調用這些函數,進而允許在建構表單元素時對該 元素進行額外的操作。例如,在modules/system/system.module定義了checkboxes類型,在建構表單期間,将調用 includes/form.inc裡面的函數expand_checkboxes():
$type['checkboxes'] = array(
'#input' => TRUE,
'#process' => array('expand_checkboxes'),
'#tree' => TRUE
);
還可參看本章中“收集所有可能的表單元素定義”部分中的例子。當#process數組中的所有的函數都被調用以後,将為每個表單元素添加一個#processed屬性。
#after_build
該屬性是一個函數數組,在建構完表單元素以後它們将被立即調用。每個要被調用的函數都有兩個參數:$form 和 $form_state。例如,如果$form['#after_build'] = array('foo', 'bar'),那麼Drupal在表單元素建構完以後,分别調用foo($form, $form_state)和bar($form, $form_state)。一旦這些函數都被調用以後,Drupal在内部将為每個表單元素添加一個#after_build_done屬性。
#theme
該可選屬性定義了一個字元串,當Drupal為該表單元素尋找主題函數時使用。例如,設定#theme = 'foo',Drupal将會在主題系統資料庫中查找對應于foo的條目。參看本章前面的“為表單尋找主題函數”一節。
#prefix
該屬性是一個字元串,在表單元素呈現時,它将被添加到表單元素的前面。
#suffix
該屬性是一個字元串,在表單元素呈現時,它将被添加到表單元素的後面。
#title
該字元串是表單元素的标題。
#weight
該屬性可以是一個整數或者小數。當呈現表單元素時,将根據它們的重量進行排序。重量小的元素将被放到前面,重量大的元素将被放到後面。
#default_value
該屬性的類型取決于表單元素的類型。對于輸入表單元素,如果表單還沒有被送出,那麼它就是在該字段中所用的值。不要将它與表單元素#value混淆了。表 單元素#value定義了一個内部表單值,盡管使用者看不到它,但是它卻定義在表單中,并出現在$form_state['values']中。