月度归档 2014年12月31日

通过清心醉

PHP 返回值

该方法对C++相同,只是定义变量和函数方法不同

如果用面向过程的方式写小程序,返回值可能不常用上.(起码作者自学的时候,没用过返回值.)但如果要涉及到了面向对象,程序返回值的使用是一门必须掌握的.

上一段简单的返回值介绍.(作者自学的时候也有看,网上的大部分只说返回一个值,可是却没说返回值怎么用?有什么好处?)

<?php
function myreturn($max,$min)
{
$myreturn=($max>$min)?$max:$min;
//三元运算判断最大
return $myreturn;
//返回一个最大值
}
//定义两个变量
$a=100;
$b=991;
echo “a=”.$a.”</br>”;
echo “b=”.$b.”</br>”;
echo “最大值是”.$c=myreturn($a,$b);
//这就是关键了,$c的参数=myreturn函数,同时把$a,$b两个传值进去进行比较
//然后通过return $myreturn返回的最大值赋值回给$c

通过清心醉

PHP上传图片文件方法

function uploadfile()
{
?>
<form action=”” method=”post” name=”uploadfile” enctype=”multipart/form-data”>
<center>上传文件:<input type=”file” name=”upfile” /></center><br>
<center><input type=”submit” value=”上传” /></center></form>
<?php
if(is_uploaded_file(@$_FILES[“upfile”][“tmp_name”]))
{
$upfile=$_FILES[“upfile”];    //获取上传文件数组里面的值
$name=$upfile[“name”];//获取上传文件数组里面的文件名
$type=$upfile[“type”];//获取上传文件数组里面的类型
$size=$upfile[“size”];//获取上传文件数组里面的大小
$tmp_name=$upfile[“tmp_name”];//获取上传文件数组里面的临时存放路径
switch ($type)
{//判断type类型
case ‘image/pjpeg’:$fileok=true; //$fileok的值为true(真)
break;
case ‘image/jpeg’:$fileok=true;        break;
case ‘image/gif’:$fileok=true;        break;
case ‘image/png’:$fileok=true;        break;
}
if($size>500000)
{
echo “文件过大”;echo “<script>setTimeout(\”this.location=’index.php’\”,2000);</script>”;;
exit;
}
if($fileok) //如果返回为真,执行下面代码:
{
$error=$upfile[“error”];//上传后系统返回的值
//把上传的临时文件移动到image目录下面
move_uploaded_file($tmp_name,’img/’.$name);
$destination=”img/”.$name;
echo “上传信息:<br/>”;
switch($error)
{
case 0:
echo “文件上传成功啦!”;
//如果做幻灯因为有多图片的处理,到时修改幻灯片就要根据图片的ID来WHERE指定
mysql_query(“UPDATE bbs SET bbslogo= ‘$name'”); //写入sql
echo “<script>setTimeout(\”this.location=’index.php’\”,2000);</script>”;break;
case 1:echo “超过了文件大小,在php.ini文件中设置”;echo “<script>setTimeout(\”this.location=’index.php’\”,2000);</script>”;break;
case 2:echo “超过了文件的大小MAX_FILE_SIZE选项指定的值”;echo “<script>setTimeout(\”this.location=’index.php’\”,2000);</script>”;break;
case 3:echo “文件只有部分被上传”;echo “<script>setTimeout(\”this.location=’index.php’\”,2000);</script>”;break;
case 4:echo “没有文件被上传”;echo “<script>setTimeout(\”this.location=’index.php’\”,2000);</script>”;break;
default:echo “上传文件大小为0”;echo “<script>setTimeout(\”this.location=’index.php’\”,2000);</script>”;break;
}
}
else
{echo “请上传jpg,gif,png等格式的图片!”;exit;echo “<script>setTimeout(\”this.location=’index.php’\”,2000);</script>”;}
}

}

通过清心醉

php正则表达式判断邮箱格式

class EmailType
{
private $mailtype;
function mailtype($mail)
{
$this->mailtype=$mail;
//PHP5.3版本前使用以下IF
//if(!ereg(“^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+”,$this->mailtype))
if(!preg_match(“/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/”,$this->mailtype))
//PHP5.3以后版本方法
{
echo “<script language=\”JavaScript\”>alert(\”邮箱格式不对\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;exit;
}

}
}

ereg和preg_match函数的差别其实就是头尾多个/

通过清心醉

PHP 生成PDO连接

一般来说,我们在编写PHP程序的时候,都会把连接SQL的配置参数写到一个文件里
然后其他需要连接的地方把文件包含进来就可以了.
mysql库模式以前有写(比如作者写的小论坛程序)
老规矩,用变量接收$_POST数据
$hostname=$_POST[“adder”];
$sqluser=$_POST[“user”];
$sqlpassword=$_POST[“password”];
$sqlname=$_POST[“sqlname”];
/*这可以增加个过滤的方法*/
$f1='”‘;$f2=’;’;//符号变量,防止混淆
$counter_file = ‘config.php’; //创建个配置文件
$fopen=fopen($counter_file,’wb’); //新建
fputs($fopen,”<?php”.”\n”);
fputs($fopen,”\$pdo=new PDO (“.$f1.”mysql:host=”.$hostname.$f2.”dbname=”.”$sqlname”.$f2.”charset=utf8″.$f1.”,”.$f1.$sqluser.$f1.”,”.$f1.$sqlpassword.$f1.”)”.$f2.”\n”);
//实例化PDO为变量$pdo,并配置包含SQL地址;数据名;字符,用户,密码;
fputs($fopen,”?>”);
fclose($fopen);

通过清心醉

Livezilla设置客服离线邮件转发

使用LIVEZILLA服务端连接后,通过以下设置即可.

邮件配置:
LiveZilla Server Admin -> Server Configuration -> Email Settings

指定收件人:
LiveZilla Server Admin -> Server Configuration -> Emails

通过清心醉

magento Fatal error: Class ‘Mage_Googlecheckout_Helper_Data’ not found

magento自1.8.1过后停用了googlecheckout,导致版本升级后,如果进入配置系统配置页出现:Fatal error: Class ‘Mage_Googlecheckout_Helper_Data’ not found错误

删除/app/code/core/Mage/GoogleCheckout/etc里面除了config.xml的文件
重新编译下就可以了
通过清心醉

pdo取代addslashes函数的安全

addslashes函数虽然能达到一定的防SQL注入效果,但却是夕阳工业了。当然,如果有很厉害的算法,还是可以处理的很强大的。

PDO模式正在逐步取代addslashes的地位,由此可见,如果php6.0的到来的话,或者PDO会被统一而且addslashes函数被抛弃。

来一个简单的PDO连接SQL添加数据的代码吧:

<?php
header(“Content-Type:text/html;charset=utf-8”);
$pdo=new PDO(“mysql:host=localhost;dbname=qingxinzui”,”root”,””);
$pdo->exec(“insert into admin(user,password)values(‘admin’,’password’)”);
echo ” 插入成功!”;
?>

首先实例化PDO到变量,并给参数赋值:

host:主机

dbname:数据库名称

后面的两个为数据库帐号密码

PDO常用方法及其应用
PDO::query() 用于有记录结果返回的操作,特别是SELECT操作
PDO::exec() 针对没有结果集合返回的操作,如INSERT、UPDATE等操作
PDO::lastInsertId() 返回上次插入操作,主键列类型是自增的最后的自增ID
PDOStatement::fetch() 获取一条记录
PDOStatement::fetchAll() 获取所有记录集

附:

创建数据库,名字为:dbsqlname

header(“Content-Type:text/html;charset=utf-8”);
$pdo=new PDO(“mysql:host=localhost”,”root”,””);//这不需要加dbname=
$pdo->query(“CREATE DATABASE dbsqlname”);

#也可以用$pdo->exec(“CREATE DATABASE dbsqlname”);

 

 

通过清心醉

ZEND认识篇->为数据库里某个表里增加数据(未过滤及判断重复)

还是在上一篇的控制器内增加新的方法;

public function adduserAction() //添加用户
{
$user=$this->getRequest()->getParam(‘user’);
$password=$this->getRequest()->getParam(‘password’);
$adduser=array(
‘user’=>$user,
‘password’=>$password
); //为SQL的字段指定参数.
$userModel=new user();
$userModel->insert($adduser);
//将数组交给insert处理获取返回值,insert是进行写入操作.
$this->render(‘addok’);
}

因为包含有模板文件:

require_once APPLICATION_PATH.’/models/IndexModel.php’;

所以直接调用ZEND封装的Zend_Db_Table里面的方法.

更多的可以参考ZEND手册.

通过清心醉

ZEND认识篇->获取数据库里某个表里的所有数据

#测试使用ZEND框架读取MYSQL某表内的所有数据

#首先我们创建个数据库,名为qingxinzui
#然后创建user表,表内有3个字段
CREATE TABLE user(id int primary key auto_increment,name varchar(64)not null,password varchar(64)not null);
#创建自增ID(建议使用),名字,密码
然后我们配置下配置文件的MYSQL
/configs/application.ini
[mysql]
db.adapter=PDO_MYSQL
db.params.host=localhost
db.params.username=root
db.params.password=
db.params.dbname=qingxinzui

#[mysql] mysql节点开始
#db.adapter=选择PDO类型的MYSQL
#db.params.host 数据库地址
#db.params.username 用户名
#db.params.password 密码(为空即不填写)
#db.params.dbname 数据库名称

我们默认使用index控制器来操作.

既然是使用框架,那么模板也就必须有那么一个对index控制器进行数据动作的文件
models目录下创建个IndexModel.php文件
写入以下代码:
class user extends Zend_Db_Table
{
#类的名字对应user数据库的user表名
#可以使用对该表的所有操作(由于继承了Zend_DB_Table)
protected $_name=’user’; //关联的表名
//protected $_primary=’id’;
//主键为id,如果创建表的时候有设置id为主键,可以不写
}
require_once APPLICATION_PATH.’/models/IndexModel.php’;
#在index控制器内别忘记了包含模板文件

同时:
init()函数是调用该控制器时自动执行,为了以后我们能更方便的管理
我们可以新增一个控制器,命名为:DbmysqlController.php(记得在controllers目录下创建)

class DbmysqlController extends Zend_Controller_Action
{
public function init()
{
/* Initialize action controller here */
$url=constant(“APPLICATION_PATH”).DIRECTORY_SEPARATOR.’configs’.DIRECTORY_SEPARATOR.’application.ini’;
$dbconfig=new Zend_Config_Ini($url,”mysql”); //读取mysql开始的节点
$db=Zend_Db::factory($dbconfig->db);//
$db->query(‘SET NAMES UTF8’);
Zend_Db_Table::setDefaultAdapter($db);
}
}
#然后在index控制器里面包含进来,这样我们其他需要用到数据连接的控制器
#直接把DbmysqlController.php包含进来就可以了.
require_once ‘DbmysqlController.php’;
#同时修改下Index控制器继承的类为 DbmysqlController
class IndexController extends DbmysqlController
{
#DbmysqlController已经继承Zend_Controller_Action控制器的方法
public function indexAction()
{
$userModel=new user(); //模板文件里已经定义要操作的表名了.
$rs=$userModel->fetchall()->toArray(); //返回数组
/*
在这里可能会很奇怪,系统怎么会知道我们要操作哪个数据库呢
其实在DbmysqlController里,读取了配置文件,已经知道哪一个
然后我们在模板里设置了一个protected $_name=’user’; //关联的表名
所以直接提取的是当前表的所有数据
ZEND框架已经封装好了这些属性.
*/
$this->view->rs=$rs;
#给当前对象的view视图生成一个属性rs,参数为数据库返回的数组
$this->render(‘index’);
}
}
#到此为止,已经获取了数据名,表名及把每行记录返回到数组$rs里了.
#我们在index.phtml视图文件中显示出来.
<?php
foreach ($this->rs as $user)
{
echo $user[‘id’].$user[‘user’].$user[‘password’].”</br>”;
}
?>

#rs数组属性的变量名取为user
输出数组属性的id,user,password数值.

到此,一个简单的使用ZEND框架获取数据库某表内的数据就简单完成了.

#注layouts里面为布局文件,别把layout.phtml文件删除,否则将不能正常显示.

通过清心醉

ZEND框架设置字符编码

ZEND框架默认的字符集是GBK,这样在测试中文的时候就会显示乱码

菜单栏里设置下

编辑->设置编码

Edit->set encoding

修改为UTF-8就可以了.

但这样只是当前的页面为UTF-8,我们需要以后新增的文件全部为UTF-8格式.

窗口->首选项->常规->工作空间里面有个文本文件编码,缺省值是GBK,修改为UTF-8即可.

window->preference->General->workspace

通过清心醉

ZEND认识篇->MVC的执行结构及编写自己的一个简单控制器

首 先必须开启apache的riterule功能,具体的可以GOOGLE。

比如作者的测试环境,默认目录为C:\xampp\htdocs 做为ZEND框架的主目录(同时也为apache的WEB根目录)

创建好了ZEND框架并且复制了ZEND库文件到library.

由于访问的是htdocs目录,但这目录内并没有index.php等引导文件。我们自己新建一个index.php文件

写入以下代码:

<?php

Header(“Location: /public/index.php”); #实现跳转到public目录下的index.php

?>

上一篇作者已经说了如何的创建自己的ZEND框架环境。

现在我们要来实现一个自己的MVC的简单功能。(其实只是VC视图和控制器,简单开始嘛)

基本执行流程:

通过riterule机制,给予访问的页面转到index.php

#htodcs/public/index.php

index.php里执行了一些基本的初始化工作之后

实例化了一个$application = new Zend_Applicatio

在这里包含了配置文件APPLICATION_PATH . ‘/configs/application.ini’

$application调用bootstrap()->run();

跳转到了Bootstrap.php

然后交给控制器IndexController.php

执行了indexAction()函数 #默认被执行了

调用/viesw/scripts/index.phtml视图

控制器的命名方法及规法:

比如要新增一个控制器text

Controllers文件夹里增加一个textController.php 文件

#在这主意,控制器的命名为<名称>+<Controller>

然后我们来编写text控制器的方法:

<?php

#在这里必须继承Zend_Controller_Action,否则该类就会被认为只是一个普通的类而不是控制器

class textController extends Zend_Controller_Action

{

public function init(){

#默认自动调用方法   可以写一个MYSQL连接类继承  Zend_Controller_Action来实现MYSQL连接的初始化等工作。

}

public function loginAction() #后面的Action不可少。

{

#自己的登录函数

$this->render(“login”);

#找到当前text控制器视图=text里文件为login的文件

#说白点就是include””;只是不需要自己加后缀和路径

#具体render函数可以选择后按F3查看

}

}

?>

然后我们还要有个视图,用来显示登录成功。

views/scripts加个文件夹,取名为text#必须和控制器名相同

在这text文件夹里面就是专门放text+Controller这个控制器对应的视图

我们在/views/scripts/text目录下增加个login.phtml视图文件(视图文件可以为php.html等)

我们来增加内容:

<h1>登录成功</h1>

如果没配置根目录index.php跳转,可以使用

127.0.0.1:88/public/text/login方式来访问。是可以正确的打开的。

这样,一个属于我们自己的简单控制器就起来了。

通过清心醉

ZEND开山篇->创建一个ZEND框架

作者以Zend Studio 10.6.2版本为例

文件->新建->示例

1

2

完成之后,在E:\XAMPP\HTDOCS\会多一个ZEND的目录(根据自己的情况而定项目路径)

左边会出现项目所有文件

3

然后我们把ZEND库文件放进来.

直接把ZendFramework\library\zend目录拷贝到

当前ZEND框架项目里的library

如作者的目录是在E:\xampp\htdocs\zend\library

 

4

 

这时候如果我们直接访问127.0.0.7/zend

注:因为zend是在htdocs目录下,本机的APACHE主目录为htdocs

5

因为在目录内没有index.php文件,所以是没有经过控制器等跳转.

好了,到此一个简单的ZEND框架就基本上算构建成功了.

由于版本不同,为了能适应不同版本的Zend Studio

也可以执行命令来创建 #注: 需要添加PHP到环境变量

不懂的可以参考

Windows添加php环境变量

Linux添加php环境变量

当然大家不同的php目录,根据自己的来做小修改即可.

命令 进入ZendFramework\bin目录

执行:

zf.bat create project E:/xampp/htdocs/zend

用命令创建一个zend项目,由于作者使用的仍是1.12版本,ZEND现在已经出了2.x的版本了,建议下载新版来使用.

 

通过清心醉

php-mysql 创建自增ID字段

<?php
$conn=mysql_connect(“127.0.0.1″,”root”,””); //连接MYSQL数据库变量
mysql_select_db(“bdname”); //选择数据库
$sql=”CREATE TABLE user(id int primary key auto_increment,name varchar(64)not null,password varchar(64)not null,text varvhar(256) not null)”;
//创建字段,id int primary key auto_increment就是创建一个主键自增的ID字段
mysql_query($sql,$conn);
$sql1=”INSERT INTO user(name,password,text)VALUES(‘name’,’password’,’mytext’)”;
//增加一行数据,这就不再需要进行ID值的设置了.
mysql_query($sql1,$conn);
?>

通过清心醉

SMTP密码找回使用之URL格式邮件发送思路

上文作者说了
生成随机数进行MD5加密后变成验证码发送给申请找回密码的邮箱
这样用户又要进入找回密码的地方输入,其实还有一个比较实用,也是现在比较多在用的
当然作者只是小猜测,安全系数未知
先来说说思路吧:
同样,用户申请找回密码的时候
生存随机数,一样可以进行MD加密,不过这个公式自己考虑哦
比如生成3组随机数,头尾两组进行MD5加取前6位(或者更多,建议别太长,因为是GET方式),中间的为随机的默认值
然后把这3组随机数合并成一个字符串变量保存到SQL;
至于判断是否重复和上面的方法是一样的.
然后把这3组随机数合并的变量字符串发送到用户邮箱
注:URL的获取,比如本地测试是127.0.0.1/
可以在系统的时候截获URL参数,比如是用域名形式http://www.qingxinzui.com 这种形式安装的
截获该URL保存到数据库的BBS表的某字段(自行添加)

格式比如为:
你在清心论坛申请找回密码功能,请点击此URL来进行密码修改
“http://”.$url.”/”.”password=”.$randid; //URL为截获的,RANDID为验证码
在这里是实现了验证码为URL 直接就可以修改了.所以加密形式要多多考虑
这很明显,GET的方式传递password=$randid,在首页(主要在MAIN.PHP页面)
增加一个if判断是否存在$_GET[“password”]
然后执行下SQL语句
查看找回密码申请的字段里是否存在和$_GET[“password”]一样的验证码
如果有就输出修改新密码的表单
如果不存在,即可以返回个404错误页面或者直接返回主页.

由于邮件中带URL容易被过滤,所以作者就没去写实际代码了,思路就在这,有需要的朋友不懂的朋友可以留言

通过清心醉

自写小论坛更新: 增加邮件申请密码找回功能

#VER 2.0 htdocs
更新功能:
1:增加邮件找回密码功能,同时修改注册邮箱为唯一参数;
2:增加过滤函数,用户可自定过滤的文字,下次改版将修改为MYSQL保存敏感字符,因为放在TXT文件可被直接访问.
而且如果放PHP文件里修改比较麻烦.

首先增加两个表:
forgotpassword //找回密码数据表
adminforgotpassword //SMTP服务器连接参数 //忘记把表名取名SMTP了,不管了先

adminforgotpassword表字段包含:
ID,SMTP服务器,SMTP端口,SMTP邮箱,SMTP用户(部分可能就是邮箱),SMTP用户密码

forgotpassword表字段包含:
ID,需要找回密码的EMAIL,验证码RANDID,找回时间:TIME,操作IP

首先说说后端设置SMTP服务器::
admin_shell_table()函数里增加一个操作选择.
<td><a href=”admin_shell.php?adminshellid=5″>SMTP管理</a></td>
这里可以看到,GET请求到admin_shell.php并且adminshellid的参数为5

我们来看admin_shell.php:
case 5: //进入SMTP管理
$shell=$bbs_system->admin_smtp(); //调用了ADMIN_SMTP函数,其实就是一个表单
/**********SMTP控制实现**********/
function admin_smtp()
{
$smtp=”SELECT *FROM adminforgotpassword”;
$tempsmtp=mysql_query($smtp);
while($row=mysql_fetch_object($tempsmtp))
{
?>
<div class=”contacts”>
<form method=”post” action=””>
<table>
<tr>
<td>SMTP服务器:</td>
<td><input name=”smtpserver” type=”text” size=”30″ maxlength=”500″ value=”<?php echo $row->smtpserver;?>”></td>
</tr>
<tr>
<td>SMTP端口:</td>
<td><input name=”smtpserverport” type=”text” size=”30″ maxlength=”500″ value=”<?php echo $row->smtpserverport;?>”></td>
</tr>
<tr>
<td>SMTP邮箱:</td>
<td><input name=”smtpusermail” type=”text” size=”30″ maxlength=”500″ value=”<?php echo $row->smtpusermail;?>”></td>
</tr>
<tr>
<td>SMTP用户(可为邮箱):</td>
<td><input name=”smtpuser” type=”text” size=”30″ maxlength=”500″ value=”<?php echo $row->smtpuser;?>”></td>
</tr>
<tr>
<td>SMTP密码:</td>
<td><input name=”smtppass” type=”password” size=”30″ maxlength=”500″ value=”<?php echo $row->smtppass;?>”></td>
</tr>
</table>
<div align=”center”><input type=”submit” name=”admin_smtp” value=”修改”></div>
</form>
<?php
}
}
因为这时候我们是在admin_shell.php把表单调用了出来,所以当填写了之后,POST的数据在admin_shell.php文件里再一次提取
if(isset($_POST[“admin_smtp”])&&isset($_POST[“admin_smtp”])) //接收的如果是admin_smtp函数
{
$smtppost=array($_POST[“smtpserver”],$_POST[“smtpserverport”],$_POST[“smtpusermail”],$_POST[“smtpuser”],$_POST[“smtppass”]); //数组化SMTP的所有参数
$filtration->filtration($smtppost); //判断是否存在过滤字符
$bbs_system->textlong($smtppost); //判断所有参数的长度.
$bbs_system->mailtype($_POST[“smtpusermail”]); //独立判断邮箱格式//用户名也可以为邮箱,暂不做判断了.
$bbs_system->admin_smtp_sql($_POST[“smtpserver”],$_POST[“smtpserverport”],$_POST[“smtpusermail”],$_POST[“smtpuser”],$_POST[“smtppass”]);//传值 //其实SMTP应该放一个文件里,但懒的改了.
}
在这里我们主要看看admin_smtp_sql函数,前面的几个只是判断的函数,具体的可在CLASS.PHP文件里查看.
function admin_smtp_sql($smtpserver,$smtpport,$smtpmail,$smtpuser,$smtppass)
{ //接受SMTP数据
$server=$smtpserver;$port=$smtpport;$mail=$smtpmail;
$user=$smtpuser;$pass=$smtppass;
$sql=”UPDATE adminforgotpassword SET smtpserver=’$server’,smtpserverport=’$port’,smtpusermail=’$mail’,smtpuser=’$user’,smtppass=’$pass'”;
mysql_query($sql);
echo “<script language=\”JavaScript\”>alert(\”修改成功\”);</script>”;
echo “<script>setTimeout(\”this.location=’admin_shell.php?adminshellid=5’\”,0);</script>”;
}
至于更多判断端口是否为25,465等等,只需要自己写个小函数然后对POST的参数判断是否放行就可以了,
作者就不再一一写出,当然,后期会加上.

这样一来,后端修改SMTP服务参数的后端控方法就有了
我们再来看看前端,当用户在登陆的时候忘记了密码,点找回密码
会跳转到forgot_password.php文件.

 

<?php

//首先肯定是要判断有无$_POST的数据,如果存在这3个参数,表示用户是在修改新密码,(已获取验证代码)

if(isset($_POST[“email”])&&!empty($_POST[“email”])&&isset($_POST[“randid”])&&!empty($_POST[“randid”])&&isset($_POST[“newpassword”])&&!empty($_POST[“newpassword”])) //如果存在以上3个参数表示为忘记密码修改.
{
$textlong1=array($_POST[“email”],$_POST[“randid”],$_POST[“newpassword”]); //数组化
$filtration->filtration($textlong1);//判断是否包含非法文字
$bbs_system->mailtype($_POST[“email”]); //单一验证email格式
$bbs_system->textlong($textlong1); //把数组传递给textlong函数判断字符是否过长
//本想在该函数里返回数组给其他函数执行判断的,但考虑文本还是留给其他文本判断吧,
$bbs_system->email_password($_POST[“email”],$_POST[“randid”],$_POST[“newpassword”]);
//把过滤了非法文字和验证邮箱格式的3个POST参数交给email_password函数处理.
}

if(isset($_POST[“email”])&&!empty($_POST[“email”])&&!isset($_POST[“randid”])) //否则获取验证代码.
{
//如果只有一个EMAIL的参数,因为上面也会有,避免被调用出来,所以判断必须没有RANDID的验证码
$forgotpassword=array($_POST[“email”],$_POST[“submit”]);
$bbs_system->mailtype($_POST[“email”]); //单一验证email格式
$filtration->filtration($forgotpassword); //验证是否包含非法文字
$emailrand=$bbs_forgotpassword->forgotpass($_POST[“email”]); //获取邮箱数据库验证的随机验证码
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;
}
else
{
//如果以上两条件不存在,输出表单
?>
<form method=”post” action=””>
<table width=”400″ align=”center”>
<tr>
<td>如果没有验证码请先输入您的邮箱::</td>
<td><input name=”email” type=”text” size=”30″ maxlength=”500″></td>
</tr>
</table>
<div align=”center”><input type=”submit” name=”submit” value=”获取验证码”></div>
</table>
</form>

</br></br></br>
<form method=”post” action=””>
<table width=”400″ align=”center”>
<tr><td>如果有验证码请在以下表单填写(暂时不进行代码简写了.)</td></tr>
<tr>
<td>请输入您的邮箱::</td>
<td><input name=”email” type=”text” size=”30″ maxlength=”500″></td>
</tr>
<tr>
<td>请输入您的验证码::</td>
<td><input name=”randid” type=”text” size=”30″ maxlength=”500″></td>
</tr>
<tr>
<td>请输入您的新密码::</td>
<td><input name=”newpassword” type=”text” size=”30″ maxlength=”500″></td>
</tr>
</table>
<div align=”center”><input type=”submit” name=”submit” value=”修改密码”></div>
</table>
</form>
</div>
<?php
}
?>

上面的代码有两个方法:1是生成验证码,2是通过验证码修改密码.
我们先看看验证代码是如何生成的:
$emailrand=$bbs_forgotpassword->forgotpass($_POST[“email”]);我们把值传递给forgotpass函数
其原型是:

private $email;
private $randid;
function forgotpass($email) //在这接收了用户的邮件,
{
$this->email=$email; //邮件赋值
$sql=”select * from admin where mail=’$this->email’ and yesno=’1′”;
//找回密码的时候,必须验证用户是否是为通过审核的.
$rs=mysql_query($sql);
if(mysql_num_rows($rs)!=0)
{//如果存在找回的邮箱并且是通过审核的,
//开始创建随机数
$temprandid=md5(rand(1,1000000)); //随机数=md5过后的1~1000000
//在这特别说下,使用MD5之后的随机数,就算别人想暴力破解,也需要很大的难度,1-1000000的MD5码前6位,挺复杂的.
$this->randid=substr($temprandid,0,6); //提取MD加密后的字符串的前6位赋值给$randid
#这里增加一个方法,判断找回密码邮件里是否存在当前要找回密码的邮箱字段,有则提示重复.
$sql1=”SELECT * FROM forgotpassword where email=’$this->email'”;
$rs1=mysql_query($sql1);
if(mysql_num_rows($rs1)!=0)
{//如果找回密码里的确存在,那么判断时间的大小,超过30分钟的话删除旧的,并且重新生成.
$time=date(“Y-m-d H:i:s”);
$tempemail=mysql_query($sql1); //提取当前找回邮件的时间
while($row=mysql_fetch_object($tempemail))
{
$t=$row->time; //获得验证码生成时间.
}
$o=strtotime($time)-strtotime($t);
//strtotime()函数将任何英文文本的日期时间描述解析为 Unix 时间戳
if($o>1800) //如果SQL找回密码里的当前用户时间大于半小时,自动清除并跳出.
{
$delsql=”delete from forgotpassword where email=’$this->email'”;
mysql_query($delsql); //删除当前密码找回记录并跳出,执行后面的重新创建
}
else
{
//时间还没超过1800秒,重复提交禁止通过
echo “<script language=\”JavaScript\”>alert(\”错误::\\n重复找回\\n\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;
exit;
}
}
$sql1 = mysql_query(“select max(id) sqlmaxid from forgotpassword”);
while($sqlmaxid = mysql_fetch_object($sql1)) //读取最大userid值得
$tempmaxid = $sqlmaxid->sqlmaxid; //提取最大id
$insqlmaxid=$tempmaxid+1; //最大id+1
$time=date(“Y-m-d H:i:s”);$ip=$_SERVER[“REMOTE_ADDR”];
mysql_query(“INSERT INTO forgotpassword(id,email,randid,time,ip)
VALUES(‘$insqlmaxid’,’$this->email’,’$this->randid’,’$time’,’$ip’)”);
return $this->sendmailto($this->email,$this->randid);//返回收信人和随机数(邮件内容)给sendmailto函数
}
else
{
//否则输出该邮箱不存在
echo “<script language=\”JavaScript\”>alert(\”邮箱不存在\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;exit;
}
}

到这里,如果用户找回密码申请成功,SQL里就有了验证码,申请的邮箱等记录了
接下来要做的,就是要把验证码发送到申请的邮箱
所以有上面的代码有这么一句:
return $this->sendmailto($this->email,$this->randid); //把申请邮箱和验证码返回给sendmailto函数
我们看看该函数:

function sendmailto($mailto,$mailbody) //接受教育收件人和验证码
{
$sql=”SELECT *FROM adminforgotpassword”;
$tempsql=mysql_query($sql); //sql语句
while($row=mysql_fetch_object($tempsql)) //提出后端设置的SMTP服务器参数
{
$smtpserver=$row->smtpserver; //SMTP服务器
$smtpserverport=$row->smtpserverport; //SMTP服务器端口
$smtpusermail=$row->smtpusermail; //SMTP服务器的用户邮箱
$smtpuser=$row->smtpuser; //SMTP服务器的用户帐号
$smtppass=$row->smtppass; //SMTP服务器的用户密码
}
$mailsubject=”修改密码验证码”; //邮件主题
$this->smtpemailto=$mailto; //收件人
$this->mailbody=”请在网站找回密码处输入该验证码:”.$mailbody; //邮件内容,在这里加上了验证代码
$mailsubject=”=?UTF-8?B?” . base64_encode($mailsubject) . “?=”; //防止乱码
$mailtype=”HTML”; //邮件格式为HTML.建议不用TXT,部分邮箱不支持.
echo “<script language=\”JavaScript\”>alert(\”验证码已发送\\n请在30分内修改密码\\n\”);</script>”;
require_once (“sendmail.php”);
//提示发送成功,本来这个要放在SENDMAIL文件里的,但由于SMTP是别人写的,作者只保证能正常调用就是
//不再进行他人的SMTP类进行修改
$smtp = new smtp($smtpserver, $smtpserverport, true, $smtpuser, $smtppass);
//这里面的一个true是表示使用身份验证,否则不使用身份验证.
$smtp->debug= true; //是否显示发送的调试信息
$smtp->sendmail($this->smtpemailto, $smtpusermail, $mailsubject, $this->mailbody, $mailtype);
//把参数返回给sendmail函数处理.
}

前面说了:
//首先肯定是要判断有无$_POST的数据,如果存在这3个参数,表示用户是在修改新密码,(已获取验证代码)
回看这一句:
$bbs_system->email_password($_POST[“email”],$_POST[“randid”],$_POST[“newpassword”]);
用户输入邮箱,验证码,新密码的时候,提交给email_password函数处理

private $email_password_mail;
private $email_password_randid;
private $email_password_newpassword;
//作者定义了三个私有的数据成员来接收参数
function email_password($mail,$randid,$newpassword)
{
$this->email_password_mail=$mail;
$this->email_password_randid=$randid;
$this->email_password_newpassword=$newpassword;
$sql=”select * from forgotpassword where email=’$this->email_password_mail'”;
//首先判断输入的EMAIL在找回密码字段是否存在
$rs=mysql_query($sql);
if(mysql_num_rows($rs)!=0) //如果存在表示的确有收到用户申请找回密码的申请
{
$time=date(“Y-m-d H:i:s”); //获得当前时间
$tempemail=mysql_query($sql); //再一次执行SQL,不过现在是要提取出数据
while($row=mysql_fetch_object($tempemail))
{
$e=$row->email;$i=$row->randid;$t=$row->time; //获得邮件用户,验证码,时间.
}
$o=strtotime($time)-strtotime($t); //判断找回的时间差
//strtotime为计算时间,具体GOOGLE
if($o>1800) //由于时间是以秒计算,判断是否超时
{
//如果时间超过30分钟,达到找回密码的最大时间,删除该条找回密码申请
$delsql=”delete from forgotpassword where email=’$this->email_password_mail'”;
mysql_query($delsql); //删除当前密码找回记录
echo “<script language=\”JavaScript\”>alert(\”超过时间限制\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;
exit; //退出脚本
}
if($i!=$this->email_password_randid) //判断验证码是否正确.
{ //如果还在时间内,判断用户输入的验证码和数据库里的是否不相同
echo “<script language=\”JavaScript\”>alert(\”验证码出错\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;
exit; //退出
}
//如果时间在范围内,验证码为真
$newpassword=md5($this->email_password_newpassword);//将用户输入的新密码进行MD5加密
$sql=”UPDATE admin SET password=’$newpassword’ WHERE mail=’$this->email_password_mail'”;
//指定用户的邮箱更新用户的密码SQL
mysql_query($sql);//执行修改当前邮箱的用户的密码,切记要使用MD5
$delsql=”delete from forgotpassword where email=’$this->email_password_mail'”;
//同时删除该用户申请找回密码的记录
mysql_query($delsql);
echo “<script language=\”JavaScript\”>alert(\”密码修改成功\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;

}
else
{
echo “<script language=\”JavaScript\”>alert(\”您输入错误或者不存在\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;exit;
}
}

很多SQL语句作者没用IF来判断是否会出错,如果是自学的问题多了,可以先用IF判断MYSQL_QUERY()是否正常执行
作者自学就是这么起来的,当更了解PHP+MYSQL之后,基本只需要查看传递的参数和语句命令就可以了.

好了,到此,一个简单的邮件找回就可以了.