Archive for the ‘PHP/Mysql’ Category

php5.3开始出现的Function ereg() is deprecated Error问题解决办法

星期天, 二月 28th, 2010

PHP 5.3 ereg() 无法正常使用,提示“Function ereg() is deprecated Error”。问题根源是php中有两种正则表示方法,一个是posix,一个是perl,php6打算废除posix的正则表示方法所以后来就加了个preg_match。此问题解决办法很简单,在ereg前加个过滤提示信息符号即可:把ereg()变成@ereg()。这样屏蔽了提示信息,但根本问题还是没有解决,php在5.2版本以前ereg都使用正常,在5.3以后,就要用preg_match来代替ereg。所以就需要变成这样,原来:

ereg("^[0-9]*$",$page)

变成:

preg_match("/^[0-9]*$/",$page)

特别提醒:posix与perl的很明显的表达区别就是是否加斜杠,所以与ereg相比,后者在正则的前后分别增加了两个”/”符号,不能缺少。
Tips:此问题在php5.2之前版本不会出现。
=====================================
好心情不知从何而来,打开窗子暮然发现:下雪了。
=====================================
从蜘蛛发现discuz X在http://www.discuz.org开始测试了

discuz in iphone

星期六, 二月 27th, 2010

这两天一直在搞这个,话不多说,先上图:
0123

PHP基于二分法的手机号码归属查询与传统查询效率比较

星期一, 二月 1st, 2010

作者:刘华栋(xhat),2010年2月,个人原创,转载请注明出处
出于对算法对于系统的影响的好奇,决定实验性的在实际生产环境中研究一下算法对系统效率的影响。二分法最重要的是对有序数据的查询定位,例如手机号码就是一个很贴切的有序排列的数据例子。
如果数据量很小,例如只有10条有序数据,要查询其中的第9条数据,轮询查询需要查询9次确定结果,二分法查询次数为3次(分别是匹配第5、8、9条记录)即可确定结果。数据量越大,二分法所带来的效率就是程2的阶乘递增,可以大大提升服务器的运行效率、提升用户等待时间、节省服务器资源。
实验环境:LAMP
实验数据:国内手机号码归属地。手机号码前7位代表一个号段,生成从1300000到1590000之间的所有号段按从小到大排列,大约30万条数据。
传统查询:对于任意手机号码,截取前7位,从数据库中第一条记录开始循环向下匹配,如果对照,则返回查询结果。

flock($fp,LOCK_SH);
$note = fread($fp,filesize('./data.php'))//读取数据
fclose($fp);
$note = explode("\n",$note);
array_pop($note);
array_shift($note);
$num = count($note);
$_data = '';
//循环查询开始
for($i=1;$i<$num;$i++){
    
$row = explode(" ",$note[$i]);
    
if($m == $row[0]){
        
$_data = $row;
        
break;
    
}
}

实测结果:最快0.03512秒、最慢0.63043秒、平均查询用时约为0.4秒。

二分法查询:对于任意手机号码,截取前7位。首先匹配数据库中最中间的第100000条数据,根据二分法原则,若匹配结果比中间值大,重新选择第二次匹配第100000到200000的中间值—-第150000条数据。以此类推,直到查询到最后一位正确的值返回结果。那么每次的查询次数小于或等于17次。

flock($fp,LOCK_SH);
$note = fread($fp,filesize('./data.php'));     //读取数据
fclose($fp);
$note = explode("\n",$note);
array_pop($note);
array_shift($note);
$num = count($note);     //统计数据库总记录数
$_data = '';
$low = 0;     //二分法两端点变量
$hight = $num;
while($m < 1599999){
    
$num = ceil(($hight + $low)/2);
    
$row = explode(" ",$note[$num]);
    
if ($m == $row[0]){
        
return $_data = $row;
        
break;
    
}else{
        
$m >= $row[0] ? $low = $num : $hight = $num;
    
}
}

实测结果:每次查询都在0.034—0.035之间。

结论:本试验可以看出,二分法数据查询效率比传统效率快10倍以上。本实验数据只有30万条,在普通的应用性数据查询时,数据量越大,越能显示出二分法的优越性(理论上讲,上千万的数据查询次数不超过30次便可准确定位),在更大量的数据的时候,查询效率或许能真的给人直观的反应。

附:本文程序演示地址:
基于二分法:http://www.liuhuadong.com/other/phone
基于传统算法查询:http://www.liuhuadong.com/other/phone/2.php
随后提供:模拟数据实验环境程序下载、生产环境下基于二分法的手机号码归属地查询程序下载

php对中文字符串的精准截取

星期三, 八月 19th, 2009

php在操作字符串的问题时间无非两个问题:
1.判断字符串编码是gbk还是unicode。
2.对相应编码采取相应截取方法。
下边3个函数即可实现此两点以达到精确截取中文字符串的目的:

// gbk截取中文字符串
function gbksub($str, $len) {
    
$tmpstr = "";
    
$strlen = $len;
    
for($i = 0; $i < $strlen; $i++) {
        
if(ord(substr($str, $i, 1)) > 0xa0) {
            
$tmpstr .= substr($str, $i, 2);
            
$i++;
        
} else
            
$tmpstr .= substr($str, $i, 1);
    
}
    
echo $tmpstr;
}
 
// utf-8 截取中文字符
function utfsub($str,$len)
{
    
for($i=0;$i<$len;$i++)
    
{
        
$temp_str=substr($str,0,1);
        
if(ord($temp_str) > 127)
        
{
            
$i++;
            
if($i<$len)
            
{
                
$new_str[]=substr($str,0,3);
                
$str=substr($str,3);
            
}
        
}
        
else
        
{
            
$new_str[]=substr($str,0,1);
            
$str=substr($str,1);
        
}
    
}
    
return join($new_str);
}
//判断字符编码
function is_gb2312($str)
{
    
for($i=0; $i<strlen($str); $i++) {
        
$v = ord( $str[$i] );
        
if( $v > 127) {
            
if( ($v >= 228) && ($v <= 233) )
            
{
                
if( ($i+2) >= (strlen($str) - 1)) return true;
                
$v1 = ord( $str[$i+1] );
                
$v2 = ord( $str[$i+2] );
                
if( ($v1 >= 128) && ($v1 <=191) && ($v2 >=128) && ($v2 <= 191) ) // utf编码
                    
return false;
                
else
                    
return true;
            
}
        
}
    
}
    
return true;
}

ajax计数器的实现

星期天, 七月 12th, 2009

本文代码实现页面计数器在无刷新情况下自动更新同步计数器数据。

<script language="javascript">
var xmlHttp;
function create(){
    
if(window.ActiveXObject){
        
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
    
}
    
else if(window.XMLHttpRequest){
        
xmlHttp=new XMLHttpRequest();
    
}
}
function count(){
    
create();
    
xmlHttp.open("GET","http://www.xxx.com/3.php?aa="+Math.random());
    
xmlHttp.onreadyStatechange=handle;
    
xmlHttp.send(null);
}
function handle(){
    
if(xmlHttp.readyState==4){
        
if(xmlHttp.status==200){document.getElementById("jishu").innerHTML=escape(xmlHttp.responseText);}
    
}
}
function myShow(){
    
window.setInterval(count,5000);
}
<
/script>
<body onload="count();myShow();">
共有<span id="jishu"><
/span>人访问
<
/body>

需要注意的是xmlhttp在刷新的时间会使用缓存,所以需要在请求的地址上加随机数(Math.random)以防止使用缓存数据。另外setInterval与setTimeout的区别是前者为间隔循环执行,后者为定时执行一次。

php判断ip黑名单

星期三, 七月 8th, 2009

学校的新闻系统要求有些新闻只开放校内ip浏览,于是重写了一个代码来实现此功能,实现后的结果是,只要把允许访问的ip列入ip.txt这个文件中即可,同时支持c类ip,例如:

ip.txt
192.168
211.67.188
211.67.191.25

代码如下:

<?php
/*
 * ip地址黑名单、白名单
 * 判断访客地址的ip是否在ip.txt中,支持c类ip
 * By xhat
 */

 
$ip = $_SERVER['REMOTE_ADDR'];
$ipArray = preg_replace("#\r\n?|\n#","",file('ip.txt'));
foreach ($ipArray as $ipTest) {
 
if (substr_count($ip, $ipTest) != "0") {
      
echo "ok";         //执行相关命令
    
die();
 
}
}
 
?>

php如何判断用户通过手机wap访问还是电脑直接访问

星期三, 四月 22nd, 2009

最近做一个手机查询系统,自然就牵扯到了此问题,那我就根据对wap的认识浅谈下通过php判断用户访问方式是通过wap访问还是电脑直接访问。
首先说最根本的解决方法:
手机访问时,会附带发送user-agent信息,这个信息里面会有手机号码信息,那么如果能取得手机号码,则可以肯定是通过手机wap访问的。但是目前中国移动已经屏蔽了user-agent信息,所以获取不到手机号码。有关系的朋友可以联系移动公司,把wap网站服务器的ip提交给中国移动,加入白名单后即可取得ua信息。目前中国联通可以直接取到手机号,对联通用户此方案可完美实施。
接下来说我的解决方案:
手机访问,原理是手机通过移动公司的代理服务器进行的访问。那么我们就可以理解是一台普通电脑使用了代理服务器。当手机通过代理服务器访问的时候,http头信息会毫无疑问的包含一个信息:via。这个信息提供了有价值的判断信息。
例如河南移动取得的via信息是:

http/1.1 hazz-b-gw001-wap(infox-wisg, huawei technologies)

河南联通的via信息是:

zxwap gateway,zte technologies

其他各省的http头信息和这个大同小异,判断是否手机访问的方案就出来了:获取http的via信息字符串看是否包含wap字符,如果有则是通过手机访问。这样做的结果是没有人能伪造手机访问,判断绝对准确。自然,这样对于网上流行的手机wap模拟器也做了屏蔽—-从根本上屏蔽。
操作代码也很简单:

// check if wap by xhat
function check_wap() {
    
return stristr($_SERVER['HTTP_VIA'],"wap") ? true : false;
}
// check over

从我查阅的资料来看,目前此方法应该是迄今互联网上准确率最高、最简单的判断手机访问方法。

Mysql编码从latin1到utf8的转换

星期二, 十月 16th, 2007

前一段时间有人要xctc旧bbs的数据库,我都不好意思给,原因是数据库编码问题我一直没有解决,给了别人打开肯定是一堆垃圾乱码。今天无论如何我是要解决这个问题,搞不定这个数据库誓不为人。

xctc这个数据库不像一般的数据库,编码中途经过很多次转换,采用的转换方法不全相通,而且mysql版本也不同,所以有一些表正常有一些表不正常,转来转去,总会出现一些乱码错误。当n年后的今天我重新打开这个数据库时,已经忘记了它的字符集,忘了它存在的版本,甚至忘了其中各表的含义。我的环境是mysql5.0.45,xctc数据库创建的时候应该是在 2001年,那时候的mysql最多算3.x,经过了4.x后的mysql5,不知道还有什么兼容性问题没(其实毫无疑问,大大的有)。首先把数据库加入到mysql5中,已经忘了当时的vbb的版本是多少,只好找个最新版本升级之,中间出错。分析表、修复表、优化表,再升级,升级成功,只是内容全是乱码。网上找很多资料,转换数据库字符集了很多次,都没有解决办法。最后根据对vbb的理解加上n多资料,终于解决这个问题。

字符集问题,导入数据库后phpmyadmin直接显示了数据库字符集为:latin1。这就好办了,把latin1转换为utf8就可以了。转的时候由于mysql版本的差异,所以导出时候需要加入 “–compatible=mysql40″参数。

D:\mysql5\bin>mysqldump -uroot -p --quick --compatible=mysql40 --default-character-set=latin1 --extended-insert=FALSE xctc > d:/xctc.sql

导出后,在phpmyadmin中新建一个数据库xctc2,字符编码设为utf8-general-ci。然后执行下列语句:

mysql -uroot -p --default-character-set=utf8 xctc2 < d:/xctc.sql

一般数据库导入不会有问题,但是xctc这个数据库中间转换太多,会有错误。错在word表,里面所有字段都是乱码,导入时会认为乱码部分为空,即所有字段内容都是空,这样就会出现记录重复。好在vbb对word表要求不高,只是一个关键词的表。解决办法是清空之,回头升级好了重建关键词即可。这样,数据库xctc2就是一个完整的utf8字符集的数据了。上传,修复,升级,重建,恢复模板。一切搞定。

新的数据已经在xctcbbs.cn上了(注:空间已挂,数据丢失) 。

discuz! 6.0 用email地址或用户名和密码登陆论坛

星期五, 九月 28th, 2007

在我心目中,没有什么论坛能与vbb媲美了,但这不能决定我们论坛就必须要用vbb。与vbb相比,discuz论坛还是很有本地特色的,它们的关系就如google与baidu,各有出色之处。我一直关注vbb,因为它的强大,代码结构紧促,但并不高效。discuz解决了这个问题,代码依然强大,利用缓存大大提升了论坛性能。加之discuz开发团队在国内的专注与论坛本身的流行,国内的应用几乎可以完全用discuz取代vbb了。

这几天调试discuz,遇到一个问题。用email和密码登陆,而不是uid或用户名。在discuz官方搜了半天,也没发现解决方案,只好自己动手。仔细研究发现uid其实是一个多余的东西,完全没必要存在于表现层,只不过后台验证密码全部统一到uid上而已。我敢断定,discuz在不久的将来肯定会取消uid的登陆方式,要么不用,要么换成email登陆。废话少说,开始说标题提出问题的解决办法。

discuz!6现有的是用户名登陆,查看discuz的代码后发现,全部登陆都归结于uid的登陆。这样的话我们同样可以用email来检测数据库,以此作为用户名的补充。这时候可能出现email与用户名重复的可能,仔细查看源代码分析就能清楚,其实这无关紧要。例如用户名如果是email地址:a@b.com,email地址也是用户名所用的email:a@b.com,这样登陆的时候无论是用哪一个(用户名还是email)都是一个地址,登陆正常。如果用户名是email地址:aa@bb.com,而注册填的email为另外一个email如:aaa@bbb.com,这样登陆的时候无论用哪个地址登陆都返回正常。其实说白了,这只是一个视觉感受问题,与后台验证没什么关系;我们可能不愿意带有@或点的用户名,如果实在不爽,干脆去修改过滤代码去掉这两个东西就ok了。

言归正传,修改方法:打开根目录下logging.php,约在107行代码为:
把代码:WHERE m.$field=’$username’ ");
修改为:WHERE m.$field=’$username’ or m.email=’$username’");

修改完即可,不用其他多余操作。当然,登陆界面可以在用户名旁边加个用email也可以登陆的提示。

ok,但愿这个小动作能为你的论坛的用户增加一些新体验。

PHPer为什么被认为是草根

星期五, 三月 30th, 2007

看到一篇文章:http://www.phpchina.com/?1/action_viewspace_itemid_2520.html
标题是:PHPer为什么被认为是草根?

看后受一些启发,给我自己有一些启发,也给我对更多phper有一层新的认识:说phper大部分是草根,是由于自己没有深入开发的结果,或说是大部分phper只是浅尝辄止。

程序员是辛苦的,是值得尊敬的,这是前提。

其实看待程序员还是要从技术角度结合人性两个方面考虑。我就见过很多程序员,利用浅尝辄止的技术开发出业务,不经意中蒙蔽了管理者,管理者又以不完整的思 维来控制团队和项目,形成一个阻止创新和发展的恶性循环;人性方面,作为程序员(当然有一批敢于创新且思进取),其自身的懒惰心理也导致了平庸的发生,其 实写程序就如做人,甚至在某些方面高于做人。

但愿更多的phper能摆脱草根的称号。