Beim Erstellen von HTML-Formularen stellen wir häufig fest, dass wir viel Ansichtscode schreiben, der sich wiederholt und in verschiedenen Projekten nur schwer wiederverwendet werden kann. Beispielsweise müssen wir jedem Eingabefeld eine Textbeschriftung zuordnen und mögliche Validierungsfehler anzeigen. Um die Wiederverwendbarkeit dieses Codes zu verbessern, können wir die seit Version 1.1.0 verfügbare Form Builder-Funktion verwenden.
Der Yii-Formulargenerator verwendet das CForm-Objekt, um den Inhalt darzustellen, der zum Beschreiben eines HTML-Formulars erforderlich ist, einschließlich der mit diesem Formular verknüpften Datenmodelle und der im Formular enthaltenen Eingabefelder , Und wie man das gesamte Formular rendert. Entwickler müssen hauptsächlich dieses CForm-Objekt erstellen und konfigurieren und dann seine Rendering-Methode aufrufen, um das Formular anzuzeigen.
Die Eingabefeldparameter des Formulars sind basierend auf den Formularelementen in einer hierarchischen Struktur organisiert. Auf der obersten Ebene der Struktur befindet sich das CForm-Objekt. Die Mitglieder dieses Objekts sind in zwei Kategorien unterteilt: CForm::buttons und CForm::elements. Ersteres enthält Schaltflächenelemente (z. B. Senden-Schaltfläche, Zurücksetzen-Schaltfläche), und letzteres enthält Eingabeelemente, statischen Text und Unterformulare. Ein Unterformular ist ebenfalls ein CForm-Objekt, existiert jedoch in den CForm::elements eines anderen Formulars. Ein Unterformular kann über ein eigenes Datenmodell, CForm::buttons- und CForm::elements-Sammlungen verfügen.
Wenn ein Benutzer ein Formular absendet, werden die in der gesamten Formularstruktur ausgefüllten Daten übermittelt, einschließlich der im Unterformular ausgefüllten Daten. CForm bietet praktische Methoden, die Eingabedaten automatisch den entsprechenden Datenattributen zuweisen und eine Datenvalidierung durchführen können.
Nachfolgend zeigen wir, wie Sie mit dem Formular-Builder ein Anmeldeformular erstellen.
Zuerst schreiben wir den Anmeldeaktionscode:
public function actionLogin() { $model = new LoginForm; $form = new CForm('application.views.site.loginForm', $model); if($form->submitted('login') && $form->validate()) $this->redirect(array('site/index')); else $this->render('login', array('form'=>$form)); }
Im obigen Code Wir erstellen ein CForm-Objekt mit den Parametern, die durch den Pfadalias application.views.site.loginForm
angegeben werden (was kurz erklärt wird). Das CForm-Objekt ist mit dem LoginForm
-Modell verknüpft (eingeführt in Modell erstellen).
Wie im Code gezeigt, leiten wir den Browser des Benutzers auf die Seite site/index
um, wenn das Formular gesendet wird und alle Eingaben fehlerfrei validiert werden. Ansonsten rendern wir die login
-Ansicht mit diesem Formular.
Der Pfadalias application.views.site.loginForm
bezieht sich tatsächlich auf die PHP-Datei protected/views/site/loginForm.php
. Diese Datei sollte ein PHP-Array zurückgeben, das die von der CForm benötigte Konfiguration wie folgt darstellt:
return array( 'title'=>'Please provide your login credential', 'elements'=>array( 'username'=>array( 'type'=>'text', 'maxlength'=>32, ), 'password'=>array( 'type'=>'password', 'maxlength'=>32, ), 'rememberMe'=>array( 'type'=>'checkbox', ) ), 'buttons'=>array( 'login'=>array( 'type'=>'submit', 'label'=>'Login', ), ), );
Configuration is ein assoziatives Array bestehend aus Schlüssel-Wert-Paaren, das zum Initialisieren der entsprechenden Eigenschaften von CForm verwendet wird. Die wichtigsten zu konfigurierenden Eigenschaften sind, wie bereits erwähnt, CForm::elements und CForm::buttons. Jeder von ihnen ist ein Array, das eine Liste von Formularelementen angibt. In den folgenden Abschnitten geben wir weitere Details zur Konfiguration von Formularelementen.
Schließlich schreiben wir die login
Ansicht, die prägnant so aussehen kann:
<h1>Login</h1> <p class="form"> <?php echo $form; ?> </p>
Tipp: Der obige Code
echo $form;
entsprichtecho $form->render();
. Dies liegt daran, dass CForm die magische Methode__toString
implementiert, dierender()
aufruft und ihr Ergebnis als Zeichenfolge zurückgibt, die dieses Formularobjekt darstellt.
Mit dem Formular-Builder wird der Großteil unserer Arbeit vom Schreiben von Ansichtsskriptcode auf die Angabe von Formularelementen übertragen. In diesem Abschnitt beschreiben wir, wie Sie das CForm::elements-Attribut angeben. Wir werden nicht über CForm::buttons sprechen, da seine Konfiguration fast die gleiche ist wie die von CForm::elements.
Die CForm::elements-Eigenschaft akzeptiert ein Array als Wert. Jedes Array-Element gibt ein separates Formularelement an, bei dem es sich um ein Eingabefeld, eine statische Textzeichenfolge oder ein Unterformular handeln kann.
Eingabeelement angeben
Ein Eingabeelement besteht hauptsächlich aus Beschriftung, Eingabefeld, Eingabeaufforderungstext und Fehleranzeige. Es muss einer Modelleigenschaft zugeordnet sein. Die Spezifikation eines Eingabeelements wird durch eine CFormInputElement-Instanz dargestellt. Der folgende Code im CForm::elements-Array gibt ein einzelnes Eingabeelement an:
'username'=>array( 'type'=>'text', 'maxlength'=>32, ),
Er veranschaulicht das Modell Das Attribut heißt username
, der Typ des Eingabefelds ist text
und sein maxlength
-Attribut ist 32.
任何 CFormInputElement 可写的属性都可以如上配置。例如,我们可以指定 hint 选项来显示提示信息,或者我们可以指定 items 选项若输入框是一个 list box,一个下拉列表,一个多选列表或一个单选按钮列表。 若选项的名字不是一个CFormInputElement 属性,它将被认为是对应 HTML 输入元素的属性, 例如,因为上面的 maxlength
不是一个CFormInputElement 属性,它被渲染作为 HTML 文本输入框的 maxlength
属性。
type 选项需要特别注意。它指定了输入框的类型。 例如,text
类型意味着将渲染一个普通的文本输入框;password
类型意味着将渲染一个密码输入框。 CFormInputElement 识别如下内置的类型:
text
hidden
password
textarea
file
radio
checkbox
listbox
dropdownlist
checkboxlist
radiolist
在上面的内置类型中,我们想要对这些 "list" 类型的用法多说一些, 包括 dropdownlist
, checkboxlist
和radiolist
。这些类型需要设置对应输入元素的 items 属性。可以这样做:
'gender'=>array( 'type'=>'dropdownlist', 'items'=>User::model()->getGenderOptions(), 'prompt'=>'Please select:', ), ... class User extends CActiveRecord { public function getGenderOptions() { return array( 0 => 'Male', 1 => 'Female', ); } }
上面的代码将生成一个下拉列表选择器,提示文字是 “please select:”。选项包括 “Male” 和 “Female”,它们是由 User
模型类中的 getGenderOptions
方法返回的。
除了这些内置的类型, type 选项也可以是一个 widget 类名字或 widget 类的路径别名。 widget 类必须扩展自CInputWidget 或 CJuiInputWidget。当渲染输入元素时, 一个指定 widget 类的实例将被创建并渲染。The widget will be configured using the specification as given for the input element.
指定静态文本
很多情况下,一个表单包含一些装饰性的 HTML 代码。 例如,一个水平线被用来分隔表单中不同的部分;一个图像出现在特定的位置来增强表单的视觉外观。 我们可以在 CForm::elements 集合中指定这些 HTML 代码作为静态文本。要这样做,我们只要指定一个静态文本字符串作为一个数组元素,在 CForm::elements 恰当的位置。例如,
return array( 'elements'=>array( ...... 'password'=>array( 'type'=>'password', 'maxlength'=>32, ), '<hr />', 'rememberMe'=>array( 'type'=>'checkbox', ) ), ...... );
在上面,我们在 password
输入框和 rememberMe
之间插入一个水平线。
静态文本最好用于文本内容和它们的位置不规则时。 若表单中的每个输入元素需要被相似的装饰,我们应当定制表单渲染方法,此章节将简短介绍。
指定子表单
子表单被用来分离一个长的表单为几个逻辑部分。 例如,我们可以分离用户注册表单为两部分:登录信息和档案信息。 每个子表单和一个数据模型有无关联均可。例如在用户注册表单,若我们存储用户登录信息和档案信息到两个分离的数据表中(表示为两个数据模型), 然后每个子表单需要和一个对应的数据模型关联。若我们存储所有信息到一个数据表中,任意一个子表单都没有数据模型,因为它们和根表单分享相同的模型。
一个子表单也表示为一个CForm 对象。要指定一个子表单,我们应当配置 CForm::elements 属性为一个类型是 form
的元素:
return array( 'elements'=>array( ...... 'user'=>array( 'type'=>'form', 'title'=>'Login Credential', 'elements'=>array( 'username'=>array( 'type'=>'text', ), 'password'=>array( 'type'=>'password', ), 'email'=>array( 'type'=>'text', ), ), ), 'profile'=>array( 'type'=>'form', ...... ), ...... ), ...... );
类似于配置一个根表单,我们主要需要为一个子表单指定 CForm::elements 属性。若一个子表单需要关联一个数据模型,我们也可以配置它的 CForm::model 属性。
有时,我们想要使用一个类代表表单,而不使用默认的 CForm 类。例如, 此小节将简短展示,我们可以扩展 CForm以定制表单渲染逻辑。 通过指定输入元素的类型为 form
,一个子表单将自动被表示为一个对象,它的类和它的父表单相同。若我们指定输入元素的类型类似于 XyzForm
(一个以 Form
结尾的字符串), 然后子表单将被表示为一个XyzForm
对象。
访问表单元素和访问数组元素一样简单。CForm::elements 属性返回一个 CFormElementCollection 对象, 它扩展自 CMap 并允许以类似于一个普通数组的方式来访问它的元素。例如,要访问登录表单中的元素 username
,我们可以使用下面的代码:
$username = $form->elements['username'];
要访问用户注册表单中的 email
元素,使用
$email = $form->elements['user']->elements['email'];
因为 CForm 为它的 CForm::elements 属性执行数组访问,上面的代码可以简化为:
$username = $form['username']; $email = $form['user']['email'];
我们已经描述了子表单。我们称一个有子表单的表单为一个嵌套表单。在这一章节, 我们使用用户注册表单作为例子来展示如何创建一个关联多个数据模型的嵌套表单。我们假设用户的认证信息存储为一个 User
模型,而用户的档案信息被存储为一个 Profile
模型。
我们首先创建 register
action 如下:
public function actionRegister() { $form = new CForm('application.views.user.registerForm'); $form['user']->model = new User; $form['profile']->model = new Profile; if($form->submitted('register') && $form->validate()) { $user = $form['user']->model; $profile = $form['profile']->model; if($user->save(false)) { $profile->userID = $user->id; $profile->save(false); $this->redirect(array('site/index')); } } $this->render('register', array('form'=>$form)); }
在上面,我们使用由 application.views.user.registerForm
指定的配置创建了表单。 在表单被提交且成功验证之后,我们尝试保存 user 和 profile 模型。 我们通过访问相应子表单对象的 model
属性来检索 user 和 profile 模型。 因为输入验证已经完成,我们调用 $user->save(false)
来跳过验证。为 profile 模型也这样做。
接下来,我们编写表单配置文件 protected/views/user/registerForm.php
:
return array( 'elements'=>array( 'user'=>array( 'type'=>'form', 'title'=>'Login information', 'elements'=>array( 'username'=>array( 'type'=>'text', ), 'password'=>array( 'type'=>'password', ), 'email'=>array( 'type'=>'text', ) ), ), 'profile'=>array( 'type'=>'form', 'title'=>'Profile information', 'elements'=>array( 'firstName'=>array( 'type'=>'text', ), 'lastName'=>array( 'type'=>'text', ), ), ), ), 'buttons'=>array( 'register'=>array( 'type'=>'submit', 'label'=>'Register', ), ), );
在上面,当指定每个子表单时,我们也指定它的 CForm::title 属性。 默认的表单渲染逻辑将封装每个子表单到一个 field-set 中,使用此属性作为它的标题。
最后,我们编写 register
视图脚本:
<h1>Register</h1> <p class="form"> <?php echo $form; ?> </p>
使用表单生成器最主要的好处是逻辑 (表单配置被存储在一个单独的文件中) 和表现 (CForm::render方法) 的分离。 这样,我们可以实现定制表单显示,通过重写 CForm::render 或提供一个局部视图来渲染表单。两种方法都可以保持表单配置的完整性,并且可以容易地重用。
当重写 CForm::render 时, 你主要需要遍历 CForm::elements 和 CForm::buttons 并调用每个表单元素的CFormElement::render 方法。例如,
class MyForm extends CForm { public function render() { $output = $this->renderBegin(); foreach($this->getElements() as $element) $output .= $element->render(); $output .= $this->renderEnd(); return $output; } }
可能我们也需要写一个视图脚本 _form
以渲染一个视图:
<?php echo $form->renderBegin(); foreach($form->getElements() as $element) echo $element->render(); echo $form->renderEnd();
要使用此视图脚本,我们需要调用:
<p class="form"> $this->renderPartial('_form', array('form'=>$form)); </p>
若一个通用的表单渲染不适用于一个特殊的表单(例如,表单为特定的元素需要不规则的装饰),在视图脚本中我们可以这样做:
some complex UI elements here <?php echo $form['username']; ?> some complex UI elements here <?php echo $form['password']; ?> some complex UI elements here
在最后的方法中,表单生成器看起来并没有带来好处,因为我们仍然需要写很多表单代码。然而,它仍然是有好处的,表单被使用一个分离的配置文件指定,这样可以帮助开发者更专注于逻辑部分。
以上就是Yii框架官方指南系列21——使用表单:使用表单生成器(CForm)的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!