Archive for the ‘PHP/Mysql’ Category

php判断访问iphone访问

星期一, 三月 29th, 2010

为discuz做的iphone版本基本完工,为了方便访问,直接在首页对iphone的访问进行了判断,然后直接跳转
无标题
使用以上代码判断,经测试效果很好。

面试经历

星期四, 三月 11th, 2010

一直认为在这个城市里面,没有多少php人才,直到昨天面试,发现一个问题竟然是从来没听说过的名词,巨受打击。
一:康盛ucenter跨域登陆的实现方式;
http协议头部分加入P3P(第一次听说这个名词)。至于p3p是什么,阅读这里。g了下发现国内对此技术关注并不是很高,只查到网易通行证在不同域登陆时采用了此;当然还有ucenter。
二:操作ucenter中实例实现同步登陆。
这个以前遇到过,只是没有总结。面试时一直把重点放在了解决通信正常的问题上,其实这完全不是重点。回来后网上查了很多此问题的解决方案,大多都不靠谱,正确解决方案应该是这样:实例ucexample_1.php中有获取cookie函数

$_COOKIE['Example_auth']

,这里面的Example_auth没有被赋值,所以不会被synlogin同步,赋值即可。解决方法有两种,都很简单,一是修改ucexample_1.php文件,把$_COOKIE['Example_auth']换成$_COOKIE['auth'],这里的auth是另外应用的cookie设置的值;

/**
 * 获取当前用户的 UID 和 用户名
 * Cookie 解密直接用 uc_authcode 函数,用户使用自己的函数
 */

if(!empty($_COOKIE['auth'])) {
    
list($Example_uid, $Example_username) = explode("t", uc_authcode($_COOKIE['auth'], 'DECODE'));
} else {
    
$Example_uid = $Example_username = '';
}

二是修改同步应用的uc.php,在synlogin里面新增一个cookie赋值语句:

_setcookie('Example_auth', _authcode($uid."t".$username, 'ENCODE'));

两种方法其实是一回事。
回顾这两个问题,发现这两个问题不是一般php人能问的出来的,所以,莫非提问题的那位是康盛的人??无论怎么说,这次面试给我留下了相当深刻的印象,让我学到了一些东西,也思考到很多东西,记之。

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("#rn?|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:mysql5bin>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上了(注:空间已挂,数据丢失) 。