表单验证详解
CodeIgniter 提供了一个全面的表单验证和数据预处理类以帮助缩减你所写的代码。
概述
在解释 CodeIgniter 的数据验证处理之前,让我们先描述一下一般的情况:
一个表单显示了。
你填写并提交了它。
如果你提交了一些无效的信息,或者可能漏掉了一个必填项,表单将会连同你的数据和错误问题的描述信息重新显示。
这个过程将继续,直到你提交了一个有效的表单。
在接收端,脚本必须:
检查必须的数据。
验证数据是否为正确的类型,合适的标准。例如,如果一个用户名被提交,它必须被验证是否只包含了允许的字符。它必须有一个最小长度,不能超过最大长度。用户名不能是已存在的他人用户名,或者甚至是一个保留字等。
清理数据使其安全。
如果需要,预格式化数据(数据需要清除空白吗?经过 HTML 编码?等。)
准备数据,插入数据库。
尽管上面的过程并不是很复杂,但是通常需要编写很多代码,而且为了显示错误信息,在网页中经常要使用多种不同的控制结构。创建表单验证虽简单,实施起来却也枯燥无味。
表单验证指南
下面是如何实施CodeIgniter表单验证的一个简易教程
为了进行表单验证,你需要这三样东西:
一个包含表单的 视图 文件。
一个包含“成功”信息的视图文件,在成功提交后将被显示。
一个接收并处理所提交数据的 控制器 函数。
让我们以一个会员注册表单为例来创建这三个玩意。
表单
使用一个文本编辑器,创建一个名叫 myform.php 的表单。在它里面放上这些代码并把它保存到你的 applications/views/ 文件夹中:
My FormUsername
Password
Password Confirm
Email Address
成功页面
使用一个文本编辑器,创建一个名叫 formsuccess.php 的表单。在它里面放上这些代码并保存到你的 applications/views/
文件夹:
My FormYour form was successfully submitted!
控制器
使用一个文本编辑器,创建一个名叫 form.php 的控制器。在它里面,放上这些代码并保存到你的 applications/controllers/
文件夹:
class Form extends CI_Controller {
function index()
{
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
}
}
?>
Try it!
要测试你的表单,请使用类似这样的URL访问你的网站:
example.com/index.php/form/
如果你提交表单你只会看到表单重新加载了。这是因为你还没有设置验证规则。
由于你还没有告诉表单验证类验证什么东西。它只是默认的返回了 FALSE (boolean false) 。 run()
方法只在全部成功匹配了你的规则才会返回 TRUE 。
解析
你会注意到在此页上面的几点:
表单 (myform.php) 是一个标准的Web表单,除了以下两点:
它使用一个 表单辅助函数 创建表单开始。
技术上,这并非必要。你可以使用标准的HTML来创建,然而,使用辅助函数的好处是它为你生成了基于你配置文件中的URL的 action URL。这使得你的应用在更改URL时更具移植性。
在表单的顶端你将注意到如下函数调用:
这个函数将会返回验证器送回的所有错误信息。如果没有错误信息,它将返回空字符串。
控制器 (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');
你的控制器现在看起来像这样:
class Form extends CI_Controller {
function index()
{
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$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');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
}
}
?>
现在留空表单域提交表单你会看到错误信息。
如果你填充所有的表单域提交表单你会看到成功页。
注意: 出现错误时表单域并没有被使用数据重新填充。稍后我们去搞这个。
使用一个数组设置验证规则
继续之前请注意,如果你更喜欢通过一个操作设置所有规则的话,向规则设定函数传递的可以是一个数组。
如果你想用这个方式,你必须这样命名你的数组键:
$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()函数中包含每个表单域的名字!
My FormUsername
Password
Password Confirm
Email Address
现在刷新你的页面并提交表单产生一个错误。你的表单域应该被重新填写了。但是,只能重新填充设置了规则(rules)的表单域。
注意:1.下面的 函数参考 节包含了可以让你重填下拉菜单,单选框和复选框的函数。
重要提示: 如果你使用一个数组作为一个表单域的名字,你必须为函数提供给它一个数组。例如:
更多信息请参考下面的 使用数组作为表单域名字 一节。
回调: 你自己的验证函数
验证系统提供了向你自己验证函数的回调。这是你可以扩展验证类以适应你的需求。例如,如果你需要执行一个数据库查询来检查用户是否选择了一个唯一的用户名,你可以创建一个回调函数做这个。咱们建个例子。
在你的控制器中,修改“username”为:
$this->form_validation->set_rules('username', 'Username', 'callback_username_check');
然后在你的控制器中添加一个新的函数名叫 username_check 。你的控制器现在看起来是这样:
class Form extends CI_Controller {
public function index()
{
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->form_validation->set_rules('username', 'Username', 'callback_username_check');
$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|is_unique[users.email]');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
}
public function username_check($str)
{
if ($str == 'test')
{
$this->form_validation->set_message('username_check', 'The %s field can not be the word "test"');
return FALSE;
}
else
{
return TRUE;
}
}
}
?>
重新载入表单并以“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');
关于语言文件的具体设置和加载请参考 语言类 说明。
更改错误定界符
在默认情况下,表单验证类会使用 (
) 标签来分割每条错误信息,以达到分段效果。你可以自行对其进行定义。
定界符统一更改
如果需要全局更改错误定界符, 可以在你的控制器中,在表单验证类加载之后添加如下代码:
$this->form_validation->set_error_delimiters('
在此例中,我们将定界符由系统默认的
更改为一个div标签。
定界符单独更改
表单验证类所提供的两种显示错误验证信息的函数,分别可以通过如下方法来设置它们的定界符:
<?php echo form_error('field name', '