写验证码的动机是之前使用的一直是别人的,想使用一下自己的作品。使用在实现了面向过程的php验证码后,便想着封装了一下。
验证码整体实现的思路是相似的:1)绘制一个画布、分配背景颜色;2)绘图;3)输出图像;4)销毁画布(释放内存)。
第一步,我实现的还是获得随机字符的方法:
/**
* 功能:随机生成一个验证码函数
* */
public function getCode(){
for( $i=0; $i<$this->_code_len; $i++ ){
$this->_content .= self::$_str[rand(0, $this->_type_pos[$this->_type])];
}
return $this->_content;
}
$code = new VerifyCode(4, 2);
echo $code->getCode();
此时实现的效果为:
第二步:绘制验证码。
我想在实例化后可以按照下面的方式调用:
$code = new VerifyCode(4, 2);
$code->setWidth(90)->setHeight(30)->setX(10)->setY(10)->show('jpg');
其中在初始化的时候,进行字符个数和类型(数字、大小写字母的组合形式)的分配。在初始化即构造函数中实现:
function __construct($code_len, $type = 0) {
$this->_code_len = $code_len;
$this->_type = $type;
}
可以通过不同的传值来验证。
其余的基本思路就是1)绘制一个画布、分配背景颜色;2)绘图;3)输出图像;4)销毁画布(释放内存)。所以,在这里直接给出完整的代码。
<?php
/**
* Verify Code class <br />
*
* $code_len 验证码显示的字符个数
* $type 验证码类型(默认 0-全为数字, 1-小写字母和数字, 2-小写、大写、数字组成)
* @author MaChaoHui<Mchgloak11520@gmail.com>
* */
class VerifyCode {
private static $_str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private $_code_len;
private $_type;
private $_type_pos = array(9, 35, 61);
private $_content = NULL;
//width, height, fontsize, x, y
private $_config = array(130, 50, 18, 0, 0);
private $_image = NULL;
function __construct($code_len, $type = 0) {
$this->_code_len = $code_len;
$this->_type = $type;
}
public function setWidth( $_width ){
$this->_config[0] = $_width;
return $this;
}
public function setHeight( $_height ){
$this->_config[1] = $_height;
return $this;
}
public function setFontSize( $_fontsize ){
$this->_config[2] = $_fontsize;
return $this;
}
public function setX( $_x ){
$this->_config[3] = $_x;
return $this;
}
public function setY( $_y ){
$this->_config[4] = $_y;
return $this;
}
/**
* 功能:随机生成一个验证码函数
* */
public function getCode(){
for( $i=0; $i<$this->_code_len; $i++ ){
$this->_content .= self::$_str[rand(0, $this->_type_pos[$this->_type])];
}
return $this->_content;
}
/**
* show verify code.
* */
public function show( $_prefix = 'png' ){
//1) 创建一个画布
if( $this->_image == NULL ){
$this->_image = imagecreatetruecolor($this->_config[0], $this->_config[1]);
}
// 分配画布背景颜色
switch ( mt_rand() % 4 ) {
case 0: $_bg = imagecolorallocate($this->_image, 250, 250, 250); break;
case 1: $_bg = imagecolorallocate($this->_image, 255, 252, 232); break;
case 2: $_bg = imagecolorallocate($this->_image, 254, 245, 243); break;
case 3: $_bg = imagecolorallocate($this->_image, 233, 255, 242); break;
}
//2) 开始绘图
//绘制背景
imagefill($this->_image, $this->_config[3], $this->_config[4], $_bg);
//分配字体颜色
/*
switch ( mt_rand() % 5 ) {
case 0: $_color = imagecolorallocate($this->_image, 111, 0, 55); break;
case 1: $_color = imagecolorallocate($this->_image, 0, 77, 0); break;
case 2: $_color = imagecolorallocate($this->_image, 0, 0, 160); break;
case 3: $_color = imagecolorallocate($this->_image, 221, 111, 0); break;
case 4: $_color = imagecolorallocate($this->_image, 220, 0, 0 ); break;
}*/
$_color[] = imagecolorallocate( $this->_image, 111, 0, 55 );
$_color[] = imagecolorallocate( $this->_image, 0, 77, 0 );
$_color[] = imagecolorallocate( $this->_image, 0, 0, 160 );
$_color[] = imagecolorallocate( $this->_image, 221, 111, 0 );
$_color[] = imagecolorallocate( $this->_image, 220, 0, 0 );
//绘制边框
//imagerectangle($this->_image, $this->_config[3], $this->_config[4],
//$this->_config[0]-1, $this->_config[1]-1, $_color[rand(0,4)]);
//添加干扰点
for( $i=0; $i<200; $i++ ){
$col = imagecolorallocate($this->_image, rand(0,255), rand(0,255), rand(0,255));
imagesetpixel($this->_image, rand(0, $this->_config[0]), rand(0, $this->_config[1]), $col);
}
//添加干扰线
for( $i=0; $i<5; $i++ ){
$col = imagecolorallocate($this->_image, rand(0,255), rand(0,255), rand(0,255));
imageline($this->_image, rand(0, $this->_config[0]), rand(0,$this->_config[1]), rand(0,$this->_config[0]), rand(0,$this->_config[1]), $col);
}
//绘制验证码内容(一个个字符绘制)
$code_con = $this->getCode();
$_length = strlen($code_con);
//$_Xoffset = ($this->_config[0] - 2 * $this->_config[3]) / $_length;
$_Yoffset = ($this->_config[1] - $this->_config[4])/2;
for ($i=0; $i < $this->_code_len; $i++) {
imagettftext($this->_image, $this->_config[2], rand(-40, 40),
$this->_config[3]+$i*$this->_config[2], $this->_config[4]+$_Yoffset, $_color[rand(0, 4)], 'ariblk.ttf', $code_con[$i]);
}
//3) 根据不同的要求输出对应格式的图像
if( $_prefix == 'png' ){
header("Content-Type:image/png");
imagepng($this->_image);
}else if( $_prefix == 'gif' ){
header("Content-Type:image/gif");
imagegif($this->_image);
}else if( $_prefix == 'jpeg' || $_prefix == 'jpg' ){
header("Content-Type:image/jpeg");
imagejpeg($this->_image);
}
}
/**
* 4) destroy canvas
* */
public function __destroy(){
if( $this->_image != NULL ) imagedestroy($this->_image);
}
}
$code = new VerifyCode(4, 2);
//echo $code->getCode();
$code->setWidth(90)->setHeight(30)->setX(10)->setY(10)->show('jpg');
?>
使用:在表单中实现
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>验证码使用</title>
</head>
<body>
<h1>验证码使用</h1>
<form name="myForm" method="post" action="#">
<label>用户名:</label><input type="text" name="username"/><br />
<label>密 码:</label><input type="password" name="passwd" /><br />
<label>验证码:</label><input type="text" name="code" />
<img src="VerifyCode.class.php" οnclick="this.src = 'VerifyCode.class.php?id='+Math.random()" /><br />
<input type="submit" value="提交" />
</form>
</body>
</html>
效果:
用文字类表达逻辑应该有助于自己能力的提升。
实践中摸索着前进!!!