Archive for the ‘PHP/Mysql’ Category

在线生成二维码

星期天, 六月 20th, 2010

二维码在国外(特别是日本,因为二维码发源于日本)用的移动互联应用比较多,由于国内近年来智能手机和移动互联网的发展迅速,二维码的应用也渐渐发热。国内目前最为广泛的二维码应用就是新版火车票,虽然现在检票还没有全面进入扫描时代,但这是早晚的事情。

二维码的方便之处在于可以以更加规范、简单的存储信息,简单的说,有点“世界普通话”的味道,这个标准可以让数据在各种物理设备间方便的存贮、转存信息和数据。
于是我抽时间写了一个在线生成二维码的程序,规范来自ISO/IEC 18004:2006,这个规范不支持中文,但在全球通用,一般应用于网址、电话的存贮。
你能看出来这个图片存贮的一句歌词么:

以上大小在htc G2-G7手机上都能被识别(一句歌词,你能读出来么:P)。
想象一下:网页的重要内容旁边都有一个二维码来表示当前内容,用户如果想把这个信息转存到手机,只需要扫描一下该二维码即可瞬间以文字信息存储到手机上;反之,如果一个纸质的内容旁边富有二维码,想转换为电脑文字数据,有是多面的方便。
再想一下:肯德基的优惠券信息直接可以以二维码方式发放和读取(事实上听同事说kfc已经这样了)。
如果生活变成这样,科技和人类智慧带给我们的幸福感是不是会更加多一点。

我刚写的一个在线生成二维码地址程序:
http://www.liuhuadong.com/labs/2weima/index.php
欢迎大家使用并提出宝贵意见

Android下扫描软件:Barcode Scanner

Assigning the return value of new by reference is deprecated in xxxx的解决办法

星期二, 四月 20th, 2010

自从php5.3,越来越多的人会遇到“Assigning the return value of new by reference is deprecated in xxxx”这样的提示,尤其是在国外产品中(例如wordpress、joolma),很多人的解决办法很简单:把php版本换回就版本就ok了。毫无疑问这是个好办法,对这种遇到问题不求甚解的态度可能会让人看到些什么。我认为要换回php的旧版本,其实是对php技术爱好者的一种羞辱(用词不当,大致是这个意思)。解决办法:php5.3开始后,废除了php中的”=&”符号,所以要想复制,直接用=引用即可。详细如下:

1、PHP5对象复制是采用引用的方式;
2、如果不采用引用方式,则需要在复制对象时加关键字 clone;
3、如果在复制的过程中,同时要变更某些属性,则增加函数_clone();

中国移动飞信通信协议分析

星期二, 四月 13th, 2010

作者:刘华栋 2010.4.13
本文目的在于探讨学习,请勿用于非学习外的任何用途,否则后果自负。

出于某些需求,要用到手机短信提醒功能,自然还是免费的好。网上流传了很多版本关于飞信的通信协议,大同小异(基本都是基于2.0的,飞信现在2010协议版本为4.0),当飞信更新了一部分协议内容时,这些流行的协议似乎有些问题出现,最典型的就是:

旧版本飞信协议支持输入任何手机号码,只要是发送者好友,即可发送手机短信。
新版本飞信协议支持输入任何飞信号码,只要是发送者好友,即可发送手机短信。
新旧版本都支持发送登陆者自身手机号码为接收手机的短信。

如果我有100个飞信好友,莫非我要记住100个飞信号码?如果我要提供一个飞信接口给大伙,莫非大伙要记住他们好友的飞信号码?
当然,写本文的目的就在于从根本上解决上述两个问题(其实是一回事)。

通过对飞信协议多个版本进行了抓包分析,发现数据包格式没什么大的变化。唯一重要的变化是第五行:

M fetion.com.cn SIP-C/4.0
F:88888888
I: 10
Q: 2 M
T: sip:99999999@fetion.com.cn;p=640
//上面一行旧版本协议这里是:
//T: tel:13599999999
C: text/plain
K: SaveHistory
L: 4

这里就出现一个问题,要想发送手机短信,提交过来手机号不行,需要提交手机号对应的飞信号码才能识别,如何才能把手机号码转换为飞信号码就是解决问题的关键。经对新协议抓包分析,发现并不能直接从手机号码转换成飞信号码,但是中间有一个很不错的变量叫做”user-id”,每个手机号对应一个飞信号码,同样对应每个user-id(至于为什么会多出来一个user-id,我想可能是飞信公司准备把飞信号码当做一种商业资源来使用吧)。其实我们用户的真正的飞信号码是这个user-id,所谓飞信号码,无非是一个数字昵称(another nickname)而已。明白这些,问题就好办了:

1.发送接收者手机号码,抓包获取该号码的user-id
2.发送请求好友列表信息(登陆后自动完成);
3.匹配1user-id,对应的飞信号码(注意格式:fetion_num@fetion.com.cn)
4.发送飞信号码、短信内容,Done

具体代码省略,关键正则函数:

//获取飞信号码
function get_fetion_id($userid, $rst) {
    
preg_match("/ri=\"sip:(\d{6,10}+)@fetion.com.cn;p=(\d{0,6}+)\"
        user-id=
\"$userid/i",$rst, $matches);
    
//同理重构函数获取user-id
    
//preg_match("/user-id=\"([0-9]+)\"/i", $rst, $matches);
    
return $matches[1];
}

这样同样还会存在一个问题:给自己手机号码发送的时候转换不到自己的自己的user-id。解决办法也很简单,只需要在手机号码提交过来最初判断一下是否为登陆号码即可,如果是,取消所有转换,直接进行第4步骤即可发送。

纸上谈兵无用,演示:
Demo1:http://www.liuhuadong.com/phoneme
Demo2:http://labs.liuhuadong.com/cmcc/index.php(暂无,睡醒后继续)
QQREADERC927A243851272DC

测试一下你的最快击键速度[附排行榜]

星期天, 四月 4th, 2010

输入速度全球排行榜。
作者:刘华栋 2010.4 原创作品,欢迎转载流传
无标题
具体使用方法很简单,打开下边这个页面,直接用键盘开始输入字母a到z,顺序不能弄错,输入完成即会自动显示用时。
虽然这可能是个无聊的作品,但还是花了我不少时间才搞定,中间涉及js、css、php、mysql,我自己的26个字母的输入记录是<5秒,具体多少忘了。我的目标是达到4s以内,不过看来希望不大。
挑战地址:http://www.liuhuadong.com/labs/top.php

tips:
数据库中使用group by的时候,可以同时使用min(字段名)/max(字段名)来获取每个group中的最值,这个sql语法简直太棒了,大大减少坐在电脑前呼出的二氧化碳含量,节能环保。

vim之gg=G

星期六, 四月 3rd, 2010

无论你是vim老手还是菜鸟,vim总会给你一些惊喜甚至是惊奇。就像今天发现gg=G全文缩进这个命令一样(或者说发现=为缩进)
例如目前代码:
无标题
使用命令:=}(当然不是标题中的gg=G,vim的微妙之处就在于你看到一个命令会联想到很多自己想要的组合命令)
无标题

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
随后提供:模拟数据实验环境程序下载、生产环境下基于二分法的手机号码归属地查询程序下载