您的位置:首页 > 编程语言 > PHP开发

3:Yii使用表单(Yii权威指南)

2013-05-01 05:14 423 查看
创建表单模型
1.如果用户输入被收集、使用然后丢弃,我们应该创建一个 表单模型
2. 如果用户的输入被收集后要保存到数据库,我们应使用一个 Active
Record

定义表单模型
class LoginForm extends CFormModel
{
public $username;
public $password;
public $rememberMe=false;
}
注:我们将这些成员变量称为 特性(attributes) 而不是 属性(properties),以区别于普通的属性(properties)。 特性(attribute)是一个主要用于存储来自用户输入或数据库数据的属性(propertiy)。

声明验证规则
如果我们想要验证用户的输入是否合法,可以定义一个rules()方法进行验证,rules()方法应该是一个返回数组return array()。例如:
public function rules()
{
return array(
array('username, password', 'required'),
array('rememberMe', 'boolean'),
array('password', 'authenticate'),
);
}
rules() 返回的每个规则必须是以下格式:

array('AttributeList', 'Validator', 'on'=>'ScenarioList', ...附加选项)


AttributeList(特性列表) 是需要通过此规则验证的特性列表字符串,每个特性名字由逗号分隔;
Validator(验证器) 指定要执行验证的种类;
on 参数是可选的,它指定此规则应被应用到的场景列表;
附加选项是一个名值对数组,用于初始化相应验证器的属性值;

针对Validator,我们有3种方法进行定义:
1) Validator 可以是模型类中一个方法的名字,并且验证方法格式必须如下结构:

public function ValidatorName($attribute,$params) { ... }


2)Validator可以说一个验证器类的名字,当此规则被应用时, 一个验证器类的实例将被创建以执行实际验证。规则中的附加选项用于初始化实例的属性值。 验证器类必须继承自 CValidator
3)
Validator
可以是一个预定义的验证器类的别名。在上面的例子中,
required
名字是CRequiredValidator 的别名,它用于确保所验证的特性值不为空。

安全的特性赋值(Controllers进行处理)
当我们已经写好了一个LoginForm的时候,当用户提交表单我们就必须对用户提交的数据进行处理了,我们可以通过块赋值(massive assignment)方式实现:

$model=new LoginForm;$model->attributes=$_POST['LoginForm'];


最后的表达式被称作 块赋值(massive assignment) ,它将 $_POST['LoginForm'] 中的每一项复制到相应的模型特性中。

1.1中的安全特性
特性如果出现在相应场景的一个验证规则中,即被认为是安全的。 例如:

array('username, password', 'required', 'on'=>'login, register'),
array('email', 'required', 'on'=>'register'),


如上所示, username 和 password 特性在 login 场景中是必填项。而 username, password 和 email 特性在 register 场景中是必填项。 于是,如果我们在 login 场景中执行块赋值,就只有 username 和 password 会被块赋值。 因为只有它们出现在 login 的验证规则中。 另一方面,如果场景是 register
,这三个特性就都可以被块赋值.
// 在登录场景中
$model=new User('login');
$model->attributes=$_POST['User'];

// 在注册场景中
$model=new User('register');
$model->attributes=$_POST['User'];

请记住,验证规则是用于检查用户输入的数据,而不是检查我们在代码中生成的数据(例如时间戳,自动产生的主键)。 因此,不要 为那些不接受最终用户输入的特性添加验证规则。

有时候我们想声明一个特性是安全的,比如用户输入的文章内容:

array('content', 'safe')


触发验证规则
对于表单模型,如果数据已经赋值了($model->attributes=$_POST['User'];),则我们可以直接调用 CModel::validate()方法,例如$model->validate()将返回一个bool值。
对于AR模型,验证中我们调用其 CActiveRecord::save() 方法时自动触发。

提取验证错误
验证完成后,任何可能产生的错误将被存储在模型对象中。 我们可以通过调用 CModel::getErrors()CModel::getError() 提取这些错误信息。
这两个方法的不同点在于第一个方法将返回 所有 模型特性的错误信息,而第二个将只返回 第一个 错误信息。

验证逻辑(action)
首先实例化需要的模型,然后将数据填充($model->attributes=$_POST['LoginForm'];),填充完毕后,我们可以进行验证($model->validate())。当验证成功后,我们会重定向浏览器到指定页面如:( $this->redirect(Yii::app()->user->returnUrl);)
注:在
login
动作中,我们使用
Yii::app()->user->returnUrl
获取之前需要身份验证的页面URL。
组件
Yii::app()->user
是一种 CWebUser (或其子类)
,它表示用户会话信息(例如 用户名,状态)。更多详情, 请参考 验证与授权.

创建表单(View)
Yii 提供了几个助手(helper)类简化视图编写。例如, 要创建一个文本输入域,我们可以调用 CHtml::textField(); 要创建一个下拉列表,则调用 CHtml::dropDownList()。
从版本 1.1.1 开始,提供了一个新的小物件 CActiveForm 以简化表单创建。 这个小物件可同时提供客户端及服务器端无缝的、一致的验证。使用 CActiveForm,:

<div class="form">
<?php $form=$this->beginWidget('CActiveForm'); ?>

<?php echo $form->errorSummary($model); ?>

<div class="row">
<?php echo $form->label($model,'username'); ?>
<?php echo $form->textField($model,'username') ?>
</div>

<div class="row">
<?php echo $form->label($model,'password'); ?>
<?php echo $form->passwordField($model,'password') ?>
</div>

<div class="row rememberMe">
<?php echo $form->checkBox($model,'rememberMe'); ?>
<?php echo $form->label($model,'rememberMe'); ?>
</div>

<div class="row submit">
<?php echo CHtml::submitButton('Login'); ?>
</div>

<?php $this->endWidget(); ?>
</div><!-- form -->


收集表格输入
有时我们想通过批量模式收集用户输入。也就是说, 用户可以为多个模型实例输入信息并将它们一次性提交。 我们将此称为 表格输入(tabular
input) ,因为这些输入项通常以 HTML 表格的形式呈现。

使用表单生成器
表单的输入框参数被组织为根据表单元素的分层结构。 在结构的顶层,是 CForm 对象。此对象的成员分为两大类: CForm::buttonsCForm::elements。前者包含
按钮元素(例如提交按钮,重设按钮),后者包含输入元素,静态文本和子表单。

创建一个简单的表单

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));
}


在上面的代码中,我们使用由路径别名 application.views.site.loginForm 指定的参数创建了 CForm 对象。 CForm 对象和 LoginForm 模型关联。
路径别名 application.views.site.loginForm 实际指的是 PHP 文件 protected/views/site/loginForm.php。此文件应当返回一个 PHP 数组,这个数组代表了 CForm 所需的配置, 如下所示:

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',
),
),
);


最后,我们编写 login 视图,可以简洁地如下所示,

<h1>Login</h1>

<div class="form">
<?php echo $form; ?>
</div>


指定输入的表单元素

'username'=>array(
'type'=>'text',
'maxlength'=>32,
),


它说明模型属性被命名为 username,输入框的类型为 text,它的 maxlength 属性为 32。
任何 CFormInputElement 可写的属性都可以如上配置。例如,我们可以指定 hint 选项来显示提示信息,或者我们可以指定 items 选项若输入框是一个
list box,一个下拉列表,一个多选列表或一个单选按钮列表。 若选项的名字不是一个 CFormInputElement 属性,它将被认为是对应
HTML 输入元素的属性, 例如,因为上面的
maxlength
不是一个 CFormInputElement 属性,它被渲染作为
HTML 文本输入框的
maxlength
属性。

这里需要说明的一个地方是type类型是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',
);
}}


指定静态文本
很多情况下,一个表单包含一些装饰性的 HTML 代码。 例如,一个水平线被用来分隔表单中不同的部分;一个图像出现在特定的位置来增强表单的视觉外观。 我们可以在 CForm::elements 集合中指定这些
HTML 代码作为静态文本。要这样做,我们只要指定一个静态文本字符串作为一个数组元素,在 CForm::elements 恰当的位置。例如

return array(
'elements'=>array(
......
'password'=>array(
'type'=>'password',
'maxlength'=>32,
),

'<hr />',

'rememberMe'=>array(
'type'=>'checkbox',
)
),
......
);


指定子表单
子表单被用来分离一个长的表单为几个逻辑部分。 例如,我们可以分离用户注册表单为两部分:登录信息和档案信息。
一个子表单也表示为一个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 属性返回一个 CFormElementCollection 对象,
它扩展自 CMap 并允许以类似于一个普通数组的方式来访问它的元素。例如,要访问登录表单中的元素
username
,我们可以使用下面的代码

$username = $form['username'];
$email = $form['user']['email'];


比如我们可以直接在View里面echo $email,可以直接输出显示表单的HTML元素。

创建一个嵌套表单
我们假设用户的认证信息存储为一个 User 模型,而用户的档案信息被存储为一个 Profile 模型。这2个的是子表单。
我们首先创建 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));
}


子表单,我们编写表单配置文件 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',
),
),
);


最后,我们编写 register 视图脚本:

<h1>Register</h1>

<div class="form">
<?php echo $form; ?>
</div>


定制表单显示
使用表单生成器最主要的好处是逻辑 (表单配置被存储在一个单独的文件中) 和表现 (CForm::render方法)
的分离。 这样,我们可以实现定制表单显示,通过重写 CForm::render 或提供一个局部视图来渲染表单。两种方法都可以保持表单配置的完整性,并且可以容易地重用。
当重写 CForm::render 时,
你主要需要遍历 CForm::elementsCForm::buttons 并调用每个表单元素的CFormElement::render 方法。例如我们解决上面的问题,使用自定义表单显示,首先请确保已经存在了:
LoginForm.php(Model)这个是表单的模型
views/site/loginForm.php(View)这个是生成表单的配置文件,
SiteControllers里面有一个方法比如function actionFormCreate() 用来作为逻辑处理
function actionFormCreate()

{

$loginFormModel = new LoginForm;

$form = new CForm('application.views.site.loginForm',$loginFormModel); //调用生产表单的配置文件和模型联系起来

$this->render('FormCreate',array('form'=>$form)); //调用显示的View

}

然后我们可以建立一个_form.php的文件来处理表单的自定义(view/site/_form.php),代码如下:
<?php

echo $form->renderBegin();

foreach($form->getElements() as $element)

{

echo $element->render().'Test';

}

echo $form->renderEnd();

?>

最后一步当然是在我们的FormCreate这个试图里面显示这个表单啦:
<div class="form">

<?php $this->renderPartial('_form', array('form'=>$form)); ?>

</div>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: