Maison >développement back-end >tutoriel php >Yii Framework Official Guide Series 21 - Utilisation des formulaires : utilisation du générateur de formulaires (CForm)
Lors de la création de formulaires HTML, nous constatons souvent que nous écrivons beaucoup de code de vue répétitif et difficile à réutiliser dans différents projets. Par exemple, pour chaque champ de saisie, nous devons lui associer un libellé de texte et afficher les éventuelles erreurs de validation. Pour améliorer la réutilisabilité de ce code, nous pouvons utiliser la fonctionnalité de création de formulaire disponible depuis la version 1.1.0.
Le générateur de formulaire Yii utilise l'objet CForm pour représenter le contenu requis pour décrire un formulaire HTML, y compris les modèles de données associés à ce formulaire et les zones de saisie présentes dans le formulaire. , Et comment restituer l'intégralité du formulaire. Les développeurs doivent principalement créer et configurer cet objet CForm, puis appeler sa méthode de rendu pour afficher le formulaire.
Les paramètres de la zone de saisie du formulaire sont organisés en une structure hiérarchique basée sur les éléments du formulaire. Au niveau supérieur de la structure se trouve l’objet CForm. Les membres de cet objet sont divisés en deux catégories : CForm::buttons et CForm::elements. Le premier contient des éléments de bouton (par exemple, un bouton de soumission, un bouton de réinitialisation) et le second contient des éléments de saisie, du texte statique et des sous-formulaires. Un sous-formulaire est également un objet CForm, mais il existe dans les CForm::elements d'un autre formulaire. Un sous-formulaire peut avoir son propre modèle de données, les collections CForm::buttons et CForm::elements.
Lorsqu'un utilisateur soumet un formulaire, les données renseignées dans toute la structure du formulaire sont soumises, y compris les données renseignées dans le sous-formulaire. CForm fournit des méthodes pratiques qui peuvent attribuer automatiquement les données d'entrée aux attributs de données correspondants et effectuer la validation des données.
Ci-dessous, nous montrons comment utiliser le générateur de formulaire pour créer un formulaire de connexion.
Tout d'abord, nous écrivons le code d'action de connexion :
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)); }
Dans le code ci-dessus, Nous créons un objet CForm en utilisant les paramètres spécifiés par l'alias de chemin application.views.site.loginForm
(qui sera expliqué brièvement). L'objet CForm est associé au modèle LoginForm
(introduit dans Création de modèle).
Comme indiqué dans le code, si le formulaire est soumis et que toutes les saisies sont validées sans erreur, nous redirigerons le navigateur de l'utilisateur vers la page site/index
. Sinon, nous rendons la vue login
avec ce formulaire.
L'alias du chemin application.views.site.loginForm
fait en fait référence au fichier PHP protected/views/site/loginForm.php
. Ce fichier doit renvoyer un tableau PHP qui représente la configuration requise par le CForm, comme suit :
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 est un tableau associatif composé de paires clé-valeur, utilisé pour initialiser les propriétés correspondantes de CForm. Les propriétés les plus importantes à configurer, comme mentionné précédemment, sont CForm::elements et CForm::buttons. Chacun d'eux est un tableau spécifiant une liste d'éléments de formulaire. Dans les sections suivantes, nous donnerons plus de détails sur la façon de configurer les éléments du formulaire.
Enfin, nous écrivons la vue login
, qui peut être concise comme ceci,
<h1>Login</h1> <p class="form"> <?php echo $form; ?> </p>
Astuce : Le code ci-dessus
echo $form;
est équivalent àecho $form->render();
. En effet, CForm implémente la méthode magique__toString
, qui appellerender()
et renvoie son résultat sous forme de chaîne représentant cet objet de formulaire.
À l'aide du générateur de formulaire, la plupart de notre travail est transféré de l'écriture du code du script de vue à la spécification des éléments du formulaire. Dans cette section, nous décrivons comment spécifier l'attribut CForm::elements. Nous n'allons pas aborder CForm::buttons car sa configuration est presque la même que celle de CForm::elements.
La propriété CForm::elements accepte un tableau comme valeur. Chaque élément du tableau spécifie un élément de formulaire distinct, qui peut être une zone de saisie, une chaîne de texte statique ou un sous-formulaire.
Spécifier l'élément de saisie
Un élément de saisie se compose principalement d'une étiquette, d'une zone de saisie, d'un texte d'invite et d'un affichage d'erreur. Il doit être associé à une propriété modèle. La spécification d'un élément d'entrée est représentée par une instance de CFormInputElement. Le code suivant dans le tableau CForm::elements spécifie un seul élément d'entrée :
'username'=>array( 'type'=>'text', 'maxlength'=>32, ),
Il illustre le modèle L'attribut est nommé username
, le type de la zone de saisie est text
et son attribut maxlength
est 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中文网(www.php.cn)!