首页 > PHP开源 > 表单验证–kohana3使用手册

表单验证–kohana3使用手册

2011年4月18日 发表评论 阅读评论

验证类被按下面给出的规则用来验证任何数据的数组。它主要用来验证表单的$_POST数据。类中有一些规则已经为我们验证了并且允许我们使用回调函数。该类允许你的每个数组域设置自己的错误信息,那么你就能构建你自己的表单了。

首先是过滤器处理的字段,然后是规则,最后是回调函数。

开始

加载库

// 创建一个新的验证(Vaildate)类的对象来验证$_POST变量
$post = new Validate($_POST);

// 合并不同的数组
$post = new Validate(array_merge($_POST, $_FILES));

// 使用工厂方法能联合操作
$post = Validate::factory($_POST)->rule('field_name', 'not_empty')
                                 ->rule('field_name2', 'email');

// 增加一个过滤规则的数组
$rules = array(

                  'field_name' => array
                  (
                      'not_empty'   => NULL,
                      'max_length'  => array(32),
                  ),

                  'field_name2' => array
                  (
                      'min_length'  => array(4),
                  ),

               );
$post = Validate::factory($_POST)->rules('field_name', $rules['field_name'])
                                 ->rules('field_name2', $rules['field_name2']);

// 你也可以直接使用$_POST数组(不推荐)
$_POST = new Validate($_POST);

增加规则(必须)

验证(Validate)对象创建好之后,你需要给你增加一些规则。他们中的一些用类本身定义。

$post = new Validate($_POST);
$post->rule('username', 'not_empty')
     ->rule('password', 'not_empty')
     ->rule('password', 'min_length', array(5))
     ->rule('password', 'max_length', array(42));

$post = Validate::factory($_POST)->rule('username', 'not_empty')
                                 ->rules(
                                           'password' => array(
                                                              'min_length' => array(5),
                                                              'max_length' => array(42),
                                                           )
                                         );

规则被回调到函数并和该函数使用一样,但是它们返回一个布尔值,所以他们能验证数据是否通过。我们可以使用我们预定义的类,php,以及我们自己的规则。

预定义函数:

$post = Validate::factory($_POST)->rule(‘age’, ‘numeric’);

PHP函数:

$post = Validate::factory($_POST)->rule(‘age’, ‘is_numeric’);

用户定义的函数:

$post = Validate::factory($_POST)->rule('age', 'Model_User::check_numeric');

	public static function check_numeric($str)
	{
		// 获得当前本地设置的允许小数点
		list($decimal) = array_values(localeconv());

		return (bool) preg_match('/^-?[0-9'.$decimal.']++$/D', (string) $str);
	}

所有字段增加一个规则

同样的规则可以一次性被定义在所有的字段,只需要用TRUE来作为字段名

// 应用not_empty规则到$_POST所有字段
$post = Validate::factory($_POST)->rule(TRUE, 'not_empty');

增加过滤器(可选)

过滤器在验证之前处理。你可以在第一个参数使用TRUE来让过滤器应用在所有字段。验证过滤器是任何可以返回字符串的PHP函数。

你也可以使用可选的第三个参数来传递一个参数组成的数组给函数。你使用的函数被调用时必须返回值到第一个参数。

注意Kohana3.x版本不再有pre_filter和post_filter()。这就意味着你将使用filter()来预过滤,如果需要,为post过滤回调。

你可以为所有字段增加一个过滤器,只要在字段名处使用TRUE

// 去掉username的空白
$post = Validate::factory($_POST)->filter('username', 'trim');

// 传递参数到过滤器函数.
// will call: htmlspecialchars($_POST['username'], ENT_QUOTES)
$post = Validate::factory($_POST)->filter('username', 'htmlspecialchars', array(ENT_QUOTES));

// 为所有字段使用一个静态定义的函数作为过滤器
$post = Validate::factory($_POST)->filter(TRUE, 'Model_User::myfilter', array($param1, $param2));
    class Model_User extends Model_Auth_User {
        public static function myfilter($value, $param1, $param2)
        {
            $value = ... //some code// ...

            return $value;
        }
    }

// 使用filters()来定义一个过滤器数组
$post = Validate::factory($_POST)->filters(
                                           'username' => array(
                                                              'Model_User::myfilter' => array($param1, $param2),
                                                              'trim' => NULL,
                                                           )
                                         );

增加回调(可选)

不同的规则,回调函数可以在字段上使用一些更复杂的验证。如果必须需要在验证对象中增加错误,那么就作为第一个参数来传递。
你可以为所有字段增加一个过滤器,只要在字段名处使用TRUE

调用 callback()方法:
用户定义的函数

// 调用用户定义的函数 reserved_username
$post = Validate::factory($_POST)->callback( 'username', 'reserved_username');

用静态方法作为回调函数

$post = Validate::factory($_POST)->callback('username', 'Model_User::mystatic_callback');

用对象的方法作为回调函数

$post = Validate::factory($_POST)->callback( 'username', array($this, 'username_available'));

用callbacks()回调数组

$post = Validate::factory($_POST)->callbacks( 'username', array(
                                                                 'reserved_username'
                                                                 'Model_User::mystatic_callback',
                                                                  array($this, 'username_available'),
                                                           )
                                            );

示例:

// 使用email_change()回调函数来验证我们的$_POST数据。
// 检查用户是否能可以改变它的email地址当该邮件地址现在还没有其他用户使用.
$post = Validate::factory($_POST)->callback('email', array($this, 'email_change'));

	/**
	 * 检验用户是否能改变email变成这样
	 *
	 * @param    Validate  $array   validate object
	 * @param    string    $field   field name
	 */
	public function email_change(Validate $array, $field)
	{
		$exists = (bool) DB::select(array('COUNT("*")', 'total_count'))
						->from($this->_table_name)
						->where('email',   '=',   $array[$field])
						->where('id',     '!=',   $this->id)
						->execute($this->_db)
						->get('total_count');

		if ($exists)
			$array->error($field, 'email_change', array($array[$field]));
	}

增加错误
你可以用error()方法增加错误

error($field, $error, array $params = NULL)

示例:

$post->error('username', 'username_available', array('johndoe'));

定义错误信息
可以在messages目录里找到国际化的文件。这些目录可以在system,application,modules目录中被发现。Kohana自己的信息文件在 system目录中。
当错误键在数组中没有被找到的时候,default键将会被使用。
例如:application/messages/register.php

 return array
(
	'email' => array(
		'email_available'    => 'The email address already exists',
                'default'  => 'Invalid Input.',
	),

	'username' => array(
		'username_available'    => 'The username already exists',
                'default'  => 'Invalid Input.',
	),

); // application/messages/register.php的结尾

如果错误信息的值在你的i18n目录中存在,那么错误信息会自动被翻译。查看翻译信息。

检索错误信息
可以用errors()方法来检索错误信息。默认返回的数组,包含字段名组成的键(key),规则组成的值(value)
检索自定义的错误信息,必须传递一个错误信息文件到errors()方法。
$errors = $validation->errors();
假定定义了一个规则,规则(‘username’,’usernam_available’) $errors 数组
包含:

array(
       ('username' => 'username_available')
      )

使用错误信息文件取得错误:

$errors = $validation->errors(‘register’)

假定你的信息目录中存在一个 register.php文件并且内容如上面写的。那么 $errors将包含:

array(
       ('username' => 'The username already exists')
      )

检索输入的数据
经过as_array()来验证插入的数据是否可进入。这对于重新填写表单字段非常有用,例如:
$_POST = array_intersect_key( $post->as_array(), $_POST);

规则

验证(Validate)类中的特定规则

规则 参数 描述 示例
not_empty 如果表单字段为空,返回FALSE
min_length 如果字段太短,返回FALSE length[5] – 最少5个字符长
max_length 如果字段太长,返回FALSE length[30]– 最多30个字符长
exact_length 如果字段太长或太短,返回FALSE length[25]– 仅可以25个字符
matches 如果字段不匹配参数,返回FALSE matches[再一次密码]
date 如果字段非有效日期,返回FALSE
regex 如果字段不符合正则表达式,返回FALSE regex[表达式] – 正则表达式来匹配(包括分隔符)
email 可选 如果email无效,返回FALSE mail[TRUE] – 严格的rfc822
email_domain 如果email域名没有有效地MX记录,返回FALSE
url 如果url无效,返回FALSE
ip 可选 如果ip无效,返回FALSE ip[TRUE] – 允许私有ip网络
credit_card 如果信用卡无效,返回FALSE credit_card[万事达卡]卡类型或者卡类型的数组
phone 可选 如果电话号码不是有效长度,返回FALSE phone[7,10,11,14] – 7,10,11或14中的一个长度(默认7,10和11)
alpha 可选 如果字段不是只有字母组成,返回FALSE alpha[TRUE] – 触发 UTF-8 兼容性
alpha_numeric 可选 如果字段不是只有字母或者数字组成,返回FALSE alpha_numeric[TRUE] – 触发 UTF-8 兼容性
alpha_dash 可选 如果字段不是只有字母,数字,下划线和破折号组成,返回FALSE alpha_dash[TRUE] – 触发 UTF-8 兼容性
digit 可选 如果字段不是只有数字字符(无点号或横线),返回FALSE digit[TRUE] – 触发UTF-8兼容
numeric 如果字段是一个无效的数字(正负或小数),返回FALSE
decimal 可选 如果字段不是完全的小数格式,可选参数是个特定的小数格式,则返回FALSE decimal – 是任何有效的小数格式

decimal[4,2] 是4个整数和2个小数

range 如果字段不是随机在最大和最小范围之内,则返回FALSE range[1,10] – 在1和10之间
color 如果字段不是一个适当的16进制HTML颜色值,则返回FALSE

示例
创建和验证表单

//验证一个用户注册
	function action_register()
	{
			#例举一个新用户
			$user = ORM::factory('user');	
 
			#加载验证规则,过滤器和回调函数
			$post = $user->validate_create($_POST);
 
                        #验证所有的字段的有效性
			if ($post->check())
			{
				#影响并清理user对象的变量
				$user->values($post);
 
				#创建账户
				$user->save();
 
				#为用户添加登录角色
				$login_role = new Model_Role(array('name' =>'login'));
				$user->add('roles',$login_role);
 
				#标记用户进入
				Auth::instance()->login($post['username'], $post['password']);
 
				#重定向用户账号
				Request::instance()->redirect('myaccount');
			}
			else
			{
                                #重新注入$_POST数据
                                $_POST = array_intersect_key( $post->as_array(), $_POST);
 
                                #影响所要进一步显示的错误
				$this->errors = $post->errors('register');
			}
           }

我们的 Model_User

class Model_User extends Model_Auth_User {
	protected $_rules = array
	(
		'username'			=> array
		(
			'not_empty'		=> NULL,
			'min_length'		=> array(4),
			'max_length'		=> array(32),
			'regex'			=> array('/^[-\pL\pN_.]++$/uD'),
		),
		'password'			=> array
		(
			'not_empty'		=> NULL,
			'min_length'		=> array(5),
			'max_length'		=> array(42),
		),
		'password_confirm'	=> array
		(
			'matches'		=> array('password'),
		),
		'email'				=> array
		(
			'not_empty'		=> NULL,
			'min_length'		=> array(4),
			'max_length'		=> array(127),
			'validate::email'	=> NULL,
		),
	);
 
	protected $_callbacks = array
	(
		'username'			=> array('username_available'),
		'email'					=> array('email_available'),
	);
 
	public function validate_create(& $array) 
	{
		// 初始化验证库并设置一些规则		
		$array = Validate::factory($array)
						->rules('password', $this->_rules['password'])
						->rules('username', $this->_rules['username'])
						->rules('email', $this->_rules['email'])
						->rules('password_confirm', $this->_rules['password_confirm'])
						->filter('username', 'trim')
						->filter('email', 'trim')
						->filter('password', 'trim')
						->filter('password_confirm', 'trim');
 
 
                #增加 Model_Auth_User 回调函数
                foreach ($this->_callbacks as $field => $callbacks)
                {
		    foreach ($callbacks as $callback){
			$array->callback($field, array($this, $callback));
		    }
		}
 
		return $array;
	}
 
 
	public function validate_change(& $array, $save = FALSE){
		// 初始化验证哭并设置一些规则		
		$array = Validate::factory($array)->rules('email', $this->_rules['email'])				
                                                  ->filter('email', 'trim')
						  ->filter('password', 'trim')
				                  ->callback('email', array($this, 'email_change'));
 
		if(trim($array['password']) != '')
			$array->rules('password', array('min_length'=> array(5), 'max_length'=>array(42)));
 
 
		return $array;		
	}	
 
 
	/**
	 * 验证用户是否改变了email成为这个
	 *
	 * @param    Validate  $array   validate object
	 * @param    string    $field   field name
	 */
	public function email_change(Validate $array, $field)
	{
		$exists = (bool) DB::select(array('COUNT("*")', 'total_count'))
						->from($this->_table_name)
						->where('email',   '=',   $array[$field])
						->where('id',     '!=',   $this->id)
						->execute($this->_db)
						->get('total_count');
 
		if ($exists)
			$array->error($field, 'email_change', array($array[$field]));
	}
 
	/**
	 * 如果用户名存在于验证规则的unique_key_exists()失败是否触发错误 
	 *
	 * @param    Validate  $array   validate object
	 * @param    string    $field   field name
	 * @param    array     $errors  current validation errors
	 * @return   array
	 */
	public function username_available(Validate $array, $field)
	{
		if ($this->unique_key_exists($array[$field])) {
			$array->error($field, 'username_available', array($array[$field]));
		}
	}
 
	/**
	 * 如果email存在于验证规则的unique_key_exists()失败,是否触发错误
	 *
	 * @param    Validate  $array   validate object
	 * @param    string    $field   field name
	 * @param    array     $errors  current validation errors
	 * @return   array
	 */
	public function email_available(Validate $array, $field)
	{
		if ($this->unique_key_exists($array[$field])) {
			$array->error($field, 'email_available', array($array[$field]));
		}
	}
 
 
	/**
	 * 测试是否是存在于数据库中唯一的键
	 *
	 * @param   mixed        value  the value to test
	 * @return  boolean
	 */
	public function unique_key_exists($value)
	{
		return (bool) DB::select(array('COUNT("*")', 'total_count'))
						->from($this->_table_name)
						->where($this->unique_key($value), '=', $value)
						->execute($this->_db)
						->get('total_count');
	}
 
	/**
	 * 允许一个模型使用email和username均为唯一标识符的情况下登录
	 *
	 * @param  string    $value   unique value
	 * @return string             field name
	 */
	public function unique_key($value)
	{
		return Validate::email($value) ? 'email' : 'username';
	}
}

验证文件上传
这里是一个验证文件上传的示例

 		$validate = Validate::factory($_FILES);
		$validate->rules('file',
			array('Upload::valid' => array(),
		              'Upload::not_empty' => array(), 
			      'Upload::type' =>array('Upload::type' => array('jpg','png','gif')), 
			      'Upload::size' => array('1M'))
		);
 
 
		if ($validate->check())
		{			
			//成功
			Upload::save($_FILES['file'],'my_image.png','./',777);			
		}
		else
		{
			//错误	
			$this->errors = $validate->errors('upload');
			print_r($this->errors);
		}

application/messages/upload.php
return array
(
	'file' => array(
	'Upload::valid'    	=> 'valid msg',
    	'Upload::not_empty'    	=> 'not_empty msg',
    	'Upload::type'    	=> 'type msg',
    	'Upload::size'    	=> 'size msg',
    	'default'  		=> 'default msg'),
);

分类: PHP开源 标签:
  1. 本文目前尚无任何评论.