表单验证详解
CodeIgniter 提供了一个全面的表单验证和数据预处理类以帮助缩减你所写的代码。
概述
在解释 CodeIgniter 的数据验证处理之前,让我们先描述一下一般的情况:
- 一个表单显示了。
- 你填写并提交了它。
- 如果你提交了一些无效的信息,或者可能漏掉了一个必填项,表单将会连同你的数据和错误问题的描述信息重新显示。
- 这个过程将继续,直到你提交了一个有效的表单。
在接收端,脚本必须:
- 检查必须的数据。
- 验证数据是否为正确的类型,合适的标准。例如,如果一个用户名被提交,它必须被验证是否只包含了允许的字符。它必须有一个最小长度,不能超过最大长度。用户名不能是已存在的他人用户名,或者甚至是一个保留字等。
- 清理数据使其安全。
- 如果需要,预格式化数据(数据需要清除空白吗?经过 HTML 编码?等。)
- 准备数据,插入数据库。
尽管上面的过程并不是很复杂,但是通常需要编写很多代码,而且为了显示错误信息,在网页中经常要使用多种不同的控制结构。创建表单验证虽简单,实施起来却也枯燥无味。
表单验证指南
下面是如何实施CodeIgniter表单验证的一个简易教程
为了进行表单验证,你需要这三样东西:
让我们以一个会员注册表单为例来创建这三个玩意。
表单
使用一个文本编辑器,创建一个名叫 myform.php 的表单。在它里面放上这些代码并把它保存到你的 applications/views/ 文件夹中:
成功页面
使用一个文本编辑器,创建一个名叫 formsuccess.php 的表单。在它里面放上这些代码并保存到你的 applications/views/ 文件夹:
控制器
使用一个文本编辑器,创建一个名叫 form.php 的控制器。在它里面,放上这些代码并保存到你的 applications/controllers/ 文件夹:
Try it!
要测试你的表单,请使用类似这样的URL访问你的网站:
example.com/index.php/form/
如果你提交表单你只会看到表单重新加载了。这是因为你还没有设置验证规则。
由于你还没有告诉表单验证类验证什么东西。它只是默认的返回了 FALSE (boolean false) 。 run() 方法只在全部成功匹配了你的规则才会返回 TRUE 。
解析
你会注意到在此页上面的几点:
表单 (myform.php) 是一个标准的Web表单,除了以下两点:
- 它使用一个 表单辅助函数 创建表单开始。 技术上,这并非必要。你可以使用标准的HTML来创建,然而,使用辅助函数的好处是它为你生成了基于你配置文件中的URL的 action URL。这使得你的应用在更改URL时更具移植性。
- 在表单的顶端你将注意到如下函数调用:
<?php echo validation_errors(); ?>
这个函数将会返回验证器送回的所有错误信息。如果没有错误信息,它将返回空字符串。
控制器 (form.php) 有一个方法: index()。这个方法初始化验证类并加载你视图中用到的 表单辅助函数 和URL 辅助函数 它也会 运行 验证程序。基于验证是否成功,它会重现表单或显示成功页面。
设置验证规则
CodeIgniter允许你为单个表单域创建多个验证规则,按顺序层叠在一起,你甚至可以同时预先处理表单域数据。要设置验证规则请使用set_rules() 函数:
$this->form_validation->set_rules();
上面的函数使用 三个 参数作为输入:
- 表单域的名字 - 就是你给表单域取的那个名字。
- 一个此表单域的 "人性化" 名字,它将被插入到错误信息中。例如,如果你有一个表单域叫做“user”你可能给它一个人性化名字叫做“用户名”。 注意: 如果你想让表单域的名字保存在一个语言文件里,请参考 翻译表单域名字.
- 为此表单域设置的验证规则。
这儿有一个示例。在你的 控制器 (form.php) 中紧接着验证初始化函数之后,添加这段代码:
$this->form_validation->set_rules('username', 'Username', 'required');
$this->form_validation->set_rules('password', 'Password', 'required');
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');
$this->form_validation->set_rules('email', 'Email', 'required');
你的控制器现在看起来像这样:
现在留空表单域提交表单你会看到错误信息。 如果你填充所有的表单域提交表单你会看到成功页。
注意: 出现错误时表单域并没有被使用数据重新填充。稍后我们去搞这个。
使用一个数组设置验证规则
继续之前请注意,如果你更喜欢通过一个操作设置所有规则的话,向规则设定函数传递的可以是一个数组。 如果你想用这个方式,你必须这样命名你的数组键:
$config = array(
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required'
),
array(
'field' => 'passconf',
'label' => 'Password Confirmation',
'rules' => 'required'
),
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'required'
)
);
$this->form_validation->set_rules($config);
级联规则(Cascading Rules)
CodeIgniter 允许你将多个规则连接在一起。让我们试一试。修改规则设置函数中的第三个参数,如下:
$this->form_validation->set_rules('username', 'Username', 'required|min_length[5]|max_length[12]|is_unique[users.username]');
$this->form_validation->set_rules('password', 'Password', 'required|matches[passconf]');
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');
$this->form_validation->set_rules('email', 'Email', 'required|valid_email|is_unique[users.email]');
上面的代码设置了一组规则:
- 用户名表单域长度不得小于5个字符以及大于12个字符。
- 密码表单域必须跟密码确认表单域的数据一致。
- 电子邮件表单域必须是一个有效邮件地址。
马上试试看!提交不合法的数据后你会看到新的错误信息跟你设置的新规则相符。在验证参考页中你可以阅读到更多规则。
预处理数据
作为上面使用的验证函数的附加,你也可以以多种方式预处理你的数据。 例如,你可以设置像这样的规则:
$this->form_validation->set_rules('username', 'Username', 'trim|required|min_length[5]|max_length[12]');
$this->form_validation->set_rules('password', 'Password', 'trim|required|min_length[8]|matches[passconf]');
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'trim|required');
$this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email');
In the above example, we are "trimming" the fields, checking for length where necessary and making sure that both password fields match.
任何接收一个参数的 PHP 函数都可以被用作一个规则,比如 htmlspecialchars(), trim() 等等。
注意: 你一般会在验证规则之后使用这些预处理功能,这样如果发生错误,原数据将会被显示在表单。
重新填充表单(Re-populating the form)
目前为止我们只处理了错误。是使用提交的数据重填表单的时候了。CodeIgniter 为此提供了几个辅助函数。你最常用到的一个是:
set_value('field name')
打开 myform.php 视图文件并使用 set_value() 函数更新每个表单域的 值 :
不要忘记在set_value()函数中包含每个表单域的名字!
现在刷新你的页面并提交表单产生一个错误。你的表单域应该被重新填写了。但是,只能重新填充设置了规则(rules)的表单域。
注意:1.下面的 函数参考 节包含了可以让你重填下拉菜单,单选框和复选框的函数。
重要提示: 如果你使用一个数组作为一个表单域的名字,你必须为函数提供给它一个数组。例如:
<input type="text" name="colors[]" value="<?php echo set_value('colors[]'); ?>" size="50" />
更多信息请参考下面的 使用数组作为表单域名字 一节。
回调: 你自己的验证函数
验证系统提供了向你自己验证函数的回调。这是你可以扩展验证类以适应你的需求。例如,如果你需要执行一个数据库查询来检查用户是否选择了一个唯一的用户名,你可以创建一个回调函数做这个。咱们建个例子。
在你的控制器中,修改“username”为:
$this->form_validation->set_rules('username', 'Username', 'callback_username_check');
然后在你的控制器中添加一个新的函数名叫 username_check 。你的控制器现在看起来是这样:
重新载入表单并以“test”作为用户名提交数据,你会看到表单域数据传递到回调函数中供你处理。
要调用一个回调函数只需把函数名加一个"callback_"前缀并放在验证规则里。如果你需要在你的回调函数中调用一个额外的参数,你只需要在回调函数后面用[]把参数(这个参数只能是字符串类型)括起来, 例如: "callback_foo[bar]", 其中bar将成为你的回调函数中的第二个参数.【译者注:第一个参数是input的value值】
注意:你也可以处理并返回传递给你的回调函数中的表单数据。如果你的回调函数返回了除布尔型的TRUE/FALSE外的任何值,它将被假定数据是你新处理过的表单数据。
设置错误信息
所有自身的错误信息位于下面的语言文件中:language/english/form_validation_lang.php
要设置你的自定义信息你可以编辑那个文件,或使用下面的函数:
$this->form_validation->set_message('rule', 'Error Message');
其中 rule 是该条定义规则的名称,Error Message 该规则会显示的错误文本。
如果你在错误信息中包含了 %s,它将插入显示出你在表单域中设置的别名。
在上面回调的例子中,, 错误信息是通过传送函数名称返回的:
$this->form_validation->set_message('username_check')
你也可以重写语言文件中的错误信息. 例如, 你可以这么做来改变"required" 规则的信息:
$this->form_validation->set_message('required', 'Your custom message here');
翻译表单域名称
如果你希望将传递给 set_rules() 函数的自然语言参数存储在一个语言文件中——使他们有一个或多个翻译版本,你可以这么做:
首先,给当前表单域自定义一个key值(通常就是表单标签的name),然后添加上lang:前缀,如下:
$this->form_validation->set_rules('first_name', 'lang:first_name', 'required');
然后,以如下语言数组(数组的key值不必包含lang前缀)的形式保存在你的语言文件中:
$lang['first_name'] = 'First Name';
注意: 开发者自定义的语言文件数组(如上例)不会自动被CI加载,你需要在控制器中手动加载:
$this->lang->load('file_name');
关于语言文件的具体设置和加载请参考 语言类 说明。
更改错误定界符
在默认情况下,表单验证类会使用 (<p>) 标签来分割每条错误信息,以达到分段效果。你可以自行对其进行定义。
- 定界符统一更改
如果需要全局更改错误定界符, 可以在你的控制器中,在表单验证类加载之后添加如下代码:
$this->form_validation->set_error_delimiters('<div class="error">', '</div>');
在此例中,我们将定界符由系统默认的 <p> 更改为一个div标签。
- 定界符单独更改
表单验证类所提供的两种显示错误验证信息的函数,分别可以通过如下方法来设置它们的定界符:
<?php echo form_error('field name', '<div class="error">', '</div>'); ?>
或者:
<?php echo validation_errors('<div class="error">', '</div>'); ?>
独立显示错误
如果你喜欢紧挨着每个表单域显示错误信息而不是显示为一个列表,你可以使用 form_error() 函数。
试一下!更改你的表单代码为下面这样:
如果没有错误信息,将不会显示。如有错误信息,会在输入框旁单独显示。
注意: 如果你的表单域名称使用的是数组形式,你必须提供该完整的数组函数。 例如:
<?php echo form_error('options[size]'); ?>
<input type="text" name="options[size]" value="<?php echo set_value("options[size]"); ?>" size="50" />
如要了解更多,请参阅 使用数组作为表单字段名称 。
将一系列验证规则保存到一个配置文件
表单验证类的一个超拽的特性是它允许你将整个应用的所有验证规则存储到一个配置文件中。你可以组织这些规则到“组”里。这些组既可以在符合controller/function的调用时自动加载,也可以在用到时你手动调用。
怎样保存你的规则
如果想要将验证规则保存在独立的文件中,你首先需要在 application/config/ 文件夹下创建一个名称为 form_validation.php的文件。 然后,将验证规则的配置信息保存在数组 $config 中即可,具体格式如下:
$config = array(
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required'
),
array(
'field' => 'passconf',
'label' => 'Password Confirmation',
'rules' => 'required'
),
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'required'
)
);
当用户触发 run() 函数时,你的验证规则会自动被控制器加载和调用。
注意:请务必要将数组名称定义成 $config.
创建多组验证规则
为了创建多组验证规则,我们需要将它们放置到子数组中。请参考下面的例子,在此例中我们设置了两组规则,组名称分别是 "signup" 和 "email"。 当然,在实际开发中,你可以根据自己的需求任意命名:
$config = array(
'signup' => array(
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required'
),
array(
'field' => 'passconf',
'label' => 'PasswordConfirmation',
'rules' => 'required'
),
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'required'
)
),
'email' => array(
array(
'field' => 'emailaddress',
'label' => 'EmailAddress',
'rules' => 'required|valid_email'
),
array(
'field' => 'name',
'label' => 'Name',
'rules' => 'required|alpha'
),
array(
'field' => 'title',
'label' => 'Title',
'rules' => 'required'
),
array(
'field' => 'message',
'label' => 'MessageBody',
'rules' => 'required'
)
)
);
调用某组验证规则
当同时存在多组规则时,为了调用某一组规则,你需要将组的名字传递给 run() 函数。 比如, 要调用上例中"signup"组下面的规则,你应该这么做:
if ($this->form_validation->run('signup') == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
将控制器和验证组关联在一起
调用某一特定验证规则组的另一方法(更自动化):将规则组的名称定义为你要关联的控制器类/函数(class/function)名称。举例来说,假设你有一个控制器名称叫做 Member,它下面有个函数叫做 signup。那么,你的控制器可能会这么写:
<?php
class Member extends CI_Controller {
function signup()
{
$this->load->library('form_validation');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
}
}
?>
在你的验证配置文件中,你需要将你的规则组命名为member/signup,形如:
$config = array(
'member/signup' => array(
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required'
),
array(
'field' => 'passconf',
'label' => 'PasswordConfirmation',
'rules' => 'required'
),
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'required'
)
)
);
当验证规则组的名称符合”控制器类名称/函数名称“(class/function)条件时,那么在 run() 函数被执行时,它所对应的规则会自动被调用。
使用数组作为表单字段名称
表单验证类支持表单字段的名称为数组,比如:
<input type="text" name="options[]" value="" size="50" />
如果你将表单字段名称定义为数组,那么在使用 Helper函数时,你必须传递给他们与字段名称一样的数组名。对应此表单字段的验证规则也同样遵循此规则。
比如,在设置此类表单字段时,你可能会用到:
$this->form_validation->set_rules('options[]', 'Options', 'required');
或者,在显示此类表单字段的验证错误信息时,你需要使用:
<?php echo form_error('options[]'); ?>
同样的,在预填充此字段的值时使用:
<input type="text" name="options[]" value="<?php echo set_value('options[]'); ?>" size="50" />
你还可以使用多维数组作为表单字段的名称,比如
<input type="text" name="options[size]" value="" size="50" />
甚至使用:
<input type="text" name="sports[nba][basketball]" value="" size="50" />
和上个例子一样,在helper函数中,你必须使用同样的名称:
<?php echo form_error('sports[nba][basketball]'); ?>
如果你选择使用那些支持多个选项的表单字段,比如checkbox,别忘了在名称之后加上空的方括号。只有这样,当用户提交表单时,所有的选项值就会被添加到 POST 数组当中:
<input type="checkbox" name="options[]" value="red" />
<input type="checkbox" name="options[]" value="blue" />
<input type="checkbox" name="options[]" value="green" />
或者你使用的时多维数组:
<input type="checkbox" name="options[color][]" value="red" />
<input type="checkbox" name="options[color][]" value="blue" />
<input type="checkbox" name="options[color][]" value="green" />
当你使用helper函数时,也同样需要添加方括号:
<?php echo form_error('options[color][]'); ?>
规则参数列表
以下列表将列出可被使用的原生规则
规则 | 参数 | 描述 | 举例 |
---|---|---|---|
required | No | 如果元素为空,则返回FALSE | |
matches | Yes | 如果表单元素的值与参数中对应的表单字段的值不相等,则返回FALSE | matches[form_item] |
is_unique | Yes | 如果表单元素的值与指定数据表栏位有重复,则返回False(译者注:比如is_unique[User.Email],那么验证类会去查找User表中Email栏位有没有与表单元素一样的值,如存重复,则返回false,这样开发者就不必另写Callback验证代码。) | is_unique[table.field] |
min_length | Yes | 如果表单元素值的字符长度少于参数中定义的数字,则返回FALSE | min_length[6] |
max_length | Yes | 如果表单元素值的字符长度大于参数中定义的数字,则返回FALSE | max_length[12] |
exact_length | Yes | 如果表单元素值的字符长度与参数中定义的数字不符,则返回FALSE | exact_length[8] |
greater_than | Yes | 如果表单元素值是非数字类型,或小于参数定义的值,则返回FALSE | greater_than[8] |
less_than | Yes | 如果表单元素值是非数字类型,或大于参数定义的值,则返回FALSE | less_than[8] |
alpha | No | 如果表单元素值中包含除字母以外的其他字符,则返回FALSE | |
alpha_numeric | No | 如果表单元素值中包含除字母和数字以外的其他字符,则返回FALSE | |
alpha_dash | No | 如果表单元素值中包含除字母/数字/下划线/破折号以外的其他字符,则返回FALSE | |
numeric | No | 如果表单元素值中包含除数字以外的字符,则返回 FALSE | |
integer | No | 如果表单元素中包含除整数以外的字符,则返回FALSE | |
decimal | No | 如果表单元素中包含非十进制数字时,则返回FALSE | |
is_natural | No | 如果表单元素值中包含了非自然数的其他数值 (其他数值不包括零),则返回FALSE。自然数形如:0,1,2,3....等等。 | |
is_natural_no_zero | No | 如果表单元素值包含了非自然数的其他数值 (其他数值包括零),则返回FALSE。非零的自然数:1,2,3.....等等。 | |
valid_email | No | 如果表单元素值包含不合法的email地址,则返回FALSE | |
valid_emails | No | 如果表单元素值中任何一个值包含不合法的email地址(地址之间用英文逗号分割),则返回FALSE。 | |
valid_ip | No | 如果表单元素的值不是一个合法的IP地址,则返回FALSE。通过可选参数"IPv4"或"IPv6"来指定 IP 地址格式。 | |
valid_base64 | No | 如果表单元素的值包含除了base64 编码字符之外的其他字符,则返回FALSE。 |
注意: 这些规则也可以作为独立的函数. 例如:
$this->form_validation->required($string);
注意: 你也可以用适合参数的本地PHP系统函数.
预处理函数参考
下面是可用的过滤函数:
名称 | 参数 | 功能描述 |
---|---|---|
xss_clean | No | 通过 XSS 过滤函数来运行数据, 详细说明见 Input 类. |
prep_for_form | No | 将特殊字符的转换,以便可以在表单域中显示 HTML 数据,而不会破坏它。. |
prep_url | No | 当URL丢失"http://" 时,添加"http://". |
strip_image_tags | No | 将图像的html代码当中的URL提取出来。 |
encode_php_tags | No | 将PHP脚本标签强制转成实体对象。 |
注意:你也可以在这里使用任何自身接收一个参数的PHP函数,例如trim, htmlspecialchars, urldecode, 等。
函数(方法)参考
下面的这些方法是让你在控制器里使用的。
$this->form_validation->set_rules();
允许您设置验证规则,如在本教程上面的章节中描述的:
$this->form_validation->run();
运行验证程序。成功返回TRUE,失败返回FALSE。您可以选择通过功能验证组的名称,例如:将一系列验证规则保存到一个配置文件.
$this->form_validation->set_message();
允许您设置自定义错误消息。看上面的设置错误信息
辅助函数参考
以下函数在调用form时自动加载无需手动载入。The following helper functions are available for use in the view files containing your forms. Note that these are procedural functions, so they do not require you to prepend them with $this->form_validation.【译者注:所有使用下列函数的表单项都必须有验证规则,规则可以为'',或者为简单的trim函数,不可为NULL】
form_error()
给这个函数提供一个表单名称,它就可以显示出对应表单存在的错误(如果有的话)。例如:
<?php echo form_error('username'); ?>
错误定界符是可供修改的。请看上面的更改错误定界符介绍。
validation_errors()
通过字符形式显示所有错误信息。例如:
<?php echo validation_errors(); ?>
错误定界符是可供修改的。请看上面的更改错误定界符介绍。
set_value()
这个函数可以用来设置input或textarea表单的值。函数的第一个参数为必填项,代表字段名称;第二个参数是可选的,用于设置表单的默认值。例如:
<input type="text" name="quantity" value="<dfn><?php echo set_value('quantity', '0'); ?></dfn>" size="50" />
上面的表单第一次加载的时候会显示“0”。
set_select()
此函数可以帮你设置好菜单里的选项。第一个参数必须包含select菜单的名称, 第二个参数用于放置每一项的值(必填),第三项可选,用于设置一个默认项 (使用TRUE/FALSE设置)。
例如:
<select name="myselect">
<option value="one" <?php echo set_select('myselect', 'one', TRUE); ?> >One</option>
<option value="two" <?php echo set_select('myselect', 'two'); ?> >Two</option>
<option value="three" <?php echo set_select('myselect', 'three'); ?> >Three</option>
</select>
控制器:$this->form_validation->set_rules('myselect'); //thinkPod 编辑于 2011-08-09
set_checkbox()
此函数可以帮你设置好复选框中的选项。第一个参数是checkbox的名称(必填), 第二个参数用于放置每一项的值(必填),第三项可选,用于设置一个默认项 (使用TRUE/FALSE设置)。
<input type="checkbox" name="mycheck[]" value="1" <?php echo set_checkbox('mycheck[]', '1'); ?> />
<input type="checkbox" name="mycheck[]" value="2" <?php echo set_checkbox('mycheck[]', '2'); ?> />
set_radio()
此函数与set_checkbox()函数相同, 用来显示单选按钮被选中的状态。
<input type="radio" name="myradio" value="1" <?php echo set_radio('myradio', '1', TRUE); ?> />
<input type="radio" name="myradio" value="2" <?php echo set_radio('myradio', '2'); ?> />