Archive for the Category » PHP / Zend «

ApnsPHP完成推送后处理错误日志的正确方法

通过苹果的apns批量发送push消息,如果中间发生错误,应该需要捕获错误发生的对象,然后对那些发生错误的消息应该在后台进行标识,这是我们常见的处理逻辑,在ApnsPHP中很好的实现了这个逻辑,大致的代码如下:


//假设前面已经有了下面一句
$message->setCustomIdentifier($id); //这里的id可以是你消息对于的数据库id

...

$push->send();
$push->disconnect();

//在发送完以后,可以进行下面的处理

$aErrorQueue = $push->getErrors();
$error_ids = array();
if (!empty($aErrorQueue)) {
foreach ($aErrorQueue AS $e) {
$error_ids[] = $e['MESSAGE']->getCustomIdentifier();
}

这里面关键的一句是 $e[‘MESSAGE’]->getCustomIdentifier();

getErrors()返回的数组,每条记录也是个数组,key为MESSAGE对应的值是个ApnsPHP_Message对象,该对象可以使用getCustomIdentifier()方法取回前面通过 setCustomIdentifier($id)传入的$id值

Yii rules验证中可以使用的占位符列表

Here’s a list of many placeholders and the validators that are using them:

  • CBooleanValidator: {true} {false}
  • CCaptchaValidator: {id}
  • CCompareValidator: {compareAttribute} {compareValue} {operator}
  • CExistValidator: {table} {column} {value}
  • CFileValidator: {file} {limit} {extensions}
  • CNumberValidator: {min} {max}
  • CRequiredValidator: {value}
  • CStringValidator: {min} {max} {length}
  • CTypeValidator: {type}
  • CUniqueValidator: {table} {column} {value}
  • CUrlValidator: {schemes}

Of course, {attribute} is known in all validators. So, which placeholders are known depends on the validator and the condition as well: By default {min} is only used when the value is below the min value (as defined in rules) and {max} when the value is above the max value.

PHP 正则里面的两个重要技巧

正则用了好些年,有两个东西总结出来是在web开发中非常有用的,尤其在抓取、代码分析中经常用到。

1. .* 的贪吃性

我们用 /\*.*\*/ 去和字符串 /* first comment */ not comment /* second comment */ 匹配会失败,因为由于 .* 项目的贪吃性,会匹配成整个字符串,于是就会匹配失败,不过,如果在后面加一个问号数量符,则会停止贪吃性,而变成匹配尽可能少的数目,因此模式 /\*.*?\*/ 就会正确匹配。各种数量符的含义并没有改变,只是优先的匹配数目。不要将问号的此用法和其自己作为数量符的使用混淆。因为有两种用法,有时可以两个一起出现,例如 \d??\d 会优先匹配一个数字,但如别无选择也可以匹配两个以使剩余模式匹配。

如果设定了 PCRE_UNGREEDY 选项(此选项 Perl 中没有)则数量符默认不是贪吃型的,但是在个别模式后加上一个问号可以将其变成贪吃型的。换句话说,这可以反转默认的行为。

后面跟上一个 + 的数量符是“占有性”(possessive)的。它会匹配尽可能多的字符而不管剩余的模式。因此 .*abc 可以匹配 “aabc” 但是 .*+abc 就不会,因为 .*+ 已经匹配了整个字符串。自 PHP 4.3.3 起可以用占有性数量符可以来加快处理过程。

2. ()子模式的不捕获

如果将字符串 “the red king” 来和模式 the ((red|white) (king|queen))
进行匹配,捕获的子串为 “red king”,”red” 以及 “king”,并被计为 1,2 和 3。

简单的括号实现两种功能的事实不总是有帮助的。经常有需要一组子模式但不需要捕获的时候。如果左括号后面跟着 “?:”,子模式不做任何捕获,并且在计算任何之后捕获的子模式时也不算在内。例如,如果用字符串 “the white queen” 去和模式 the ((?:red|white) (king|queen)) 匹配,捕获的子串是 “white queen” 和 “queen”,并被计为 1 和 2。

因此,最完美的匹配网页中图片 src 部分的正则表达式处理如下:

$str='<p style="padding: 0px; margin-top: 0px; margin-bottom: 0px; line-height: 200%;"><img border="0" src="upfiles/2009/07/1246430143_4.jpg" alt=""/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 0px; line-height: 200%;"><img border="0" src=\'upfiles/2009/07/1246430143_3.jpg\' alt=""/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 0px; line-height: 200%;"><img border="0" src="upfiles/2009/07/1246430143_1.jpg" alt=""/><img width="280" height="187" alt="" class="imgloading" original="http://s.yoututuan.com/team/2011/1206/13231497847660.jpg" src="http://s.yoututuan.com/team/2011/1206/13231497847660.jpg" style="display: block; ">';
 
$pattern="/<img.*?src=['|\"](.*?(?:\.(?:gif|jpg)))['|\"].*?[\/]?>/i";
preg_match_all($pattern,$str,$match);
 
print_r($match);

以上代码将输出如下内容:

Array
(
    [0] => Array
        (
            [0] => <img border="0" src="upfiles/2009/07/1246430143_4.jpg" alt=""/>
            [1] => <img border="0" src='upfiles/2009/07/1246430143_3.jpg' alt=""/>
            [2] => <img border="0" src="upfiles/2009/07/1246430143_1.jpg" alt=""/>
            [3] => <img width="280" height="187" alt="" class="imgloading" original="http://s.yoututuan.com/team/2011/1206/13231497847660.jpg" src="http://s.yoututuan.com/team/2011/1206/13231497847660.jpg" style="display: block; ">
        )

    [1] => Array
        (
            [0] => upfiles/2009/07/1246430143_4.jpg
            [1] => upfiles/2009/07/1246430143_3.jpg
            [2] => upfiles/2009/07/1246430143_1.jpg
            [3] => http://s.yoututuan.com/team/2011/1206/13231497847660.jpg
        )

)

PHP正则匹配字符串中的标签

如果标签里面有中文、英文、数字等混排,则需要对汉字进行特殊处理,由于PCRE不支持\U \P \L之类的perl字符串处理转义,使用16进制或者Unicode进行处理,范例如下:

$str = "之二宽阔的甘家口东#标签1#标签2 #标签3。#标签4,都发$1234 ¥xc,cvm , ¥12,dflksjf如何#标签5.x #tag6.cvxcv“";
preg_match_all('/#([a-zA-Z0-9\x7f-\xff]+)/', $str, $mat);
print_r($mat);
 
preg_match("/[\x{00a5}\x{ffe5}](\d+)/u", $str, $mat);
print_r($mat);

得到的结果如下:


Array
(
[0] => Array
(
[0] => #标签1
[1] => #标签2
[2] => #标签3。
[3] => #标签4
[4] => #标签5
[5] => #tag6
)

[1] => Array
(
[0] => 标签1
[1] => 标签2
[2] => 标签3。
[3] => 标签4
[4] => 标签5
[5] => tag6
)

)
Array
(
[0] => ¥12
[1] => 12
)

补充说明:

双字节字符编码范围

1. GBK (GB2312/GB18030)
x00-xff GBK双字节编码范围
x20-x7f ASCII
xa1-xff 中文 gb2312
x80-xff 中文 gbk

2. UTF-8 (Unicode)

u4e00-u9fa5 (中文)
x3130-x318F (韩文
xAC00-xD7A3 (韩文)
u0800-u4e00 (日文)

牛逼的GMP数学运算库

搞了一晚上,搞定了一个需要使用无限长度数字运算的产品功能开发,实现权限模块的处理,使用了gmp库来完成,效果一级棒,性能好不好还不知道,不过好在不是用在高性能要求的部分,好久木有今晚这样的为了搞定一个问题而钻研的劲头了。

顺便记录一下,如果要在BSD系统下的PHP中使用GMP库,不要安装最新的5.0.x版本的GMP库,4.2.4以下的版本最好,要不编译不过去的!

当前功能中实际使用到的最大数字是 18446744073709107172 ,二进制的结果是如此惊人的长度: 1111111111111111111111111111111111111111111110010011011111100100

解决技术小问题两三件

1. imageCreateFromBMP()方法的实现,重点是解决了对32位BMP图片格式的支持,现在很多的团购网站图片格式明显有问题,比如阿丫团,虽然都是.jpg的,其实图片文件mime类型是image/bmp的,确实很诡异

2. 困扰我很久的PPT编写和修改操作电脑反应非常慢的老问题,有时输入和删除个字电脑都很迟缓,今儿终于搞定了,不是电脑的问题,是Office的拼写检查导致的,现在可以用行云流水来形容了。

3. 另外搞定SVN的菜鸟问题一个,随着版本的增加,SVN服务器的反应是越来越慢,这是因为大量的版本历史文件存放在一个服务器目录下导致,这是默认的svnadmin create的存放模式,其实使用BDB模式存放就轻松搞定了,至于为什么默认不用此方式,我还没有去研究。

pecl 升级 sphinx 到新版

转载请注明出处:[Michael`s blog] http://www.toplee.com/blog/1385.html

用pecl upgrade sphinx 命令 可以方便的完成php中sphinx模块的升级,但是这并不表示能够sphinx模块会自动增加官方描述里面的那些新特性,比如1.0.1版本里面增加了 setSelect()方法,1.0.3增加了open(), close()等方法,这些方法并不是通过 pecl upgrade就能得到的,原因是sphinx模块编译的时候需要调用的库 libsphinxclient 还需要升级更新,它们默认存在于 /usr/local/lib目录下,包括 libsphinxclient.so, libsphinxclient.a 等文件,如何升级这些库呢?

记得一定要使用和您sphinx版本一致的libsphinxclient,否则容易出问题的,至少不能高于,我就遇到了类似如下的错误提示:

client version is higher than daemon version (client is v.1.23, daemon is v.1.22)

升级的方法是用sphinx的源代码来完成编译升级,进入到sphinx源代码目录下的 api/libsphinxclient 目录,然后执行下面的命令

#sh ./buildconf.sh (通常这个是必须的,因为不同的操作系统环境)
#./configure
#make
#make install

顺利的话,这就ok了,然后您就可以pecl upgrade sphinx 后完成全部升级了。 如果运气不好,在上面make的过程中,可能出现若干错误,遇到不同的错误,仔细看错误提示,大部分都是可以自己解决的,比如,我遇到了如下的错误:

cc -g -O2 -o test test.o  .libs/libsphinxclient.a
.libs/libsphinxclient.a(sphinxclient.o)(.text+0x503): In function `set_error':
/root/packages/sphinx-1.10-beta/api/libsphinxclient/sphinxclient.c:359: undefined reference to `_vsnprintf'
*** Error code 1
cc -g -O2 -o test test.o  .libs/libsphinxclient.a.libs/libsphinxclient.a(sphinxclient.o)(.text+0x503): In function `set_error':/root/packages/sphinx-1.10-beta/api/libsphinxclient/sphinxclient.c:359: undefined reference to `_vsnprintf'*** Error code 1

这个问题解决起来很简单,只需要vi libsphinxclient.c 文件,把里面的 #define vsnprintf _vsnprintf 注释掉或者删掉就可以了,其他的问题,可以慢慢的针对具体问题具体处理。

好了,问题就说到这里了,sphinx是个不错的东东,中文方面,需要下载和安装中文分词的模块来实现,祝您使用愉快! :)

BSD下Pecl报告undefined function preg_match()错误处理

默认情况下,BSD的ports安装的PECL命令,会出现错误:
# pecl
Fatal error: Call to undefined function preg_match() in …

问题的原因是出在 /usr/local/bin/pecl 的最后一行:

exec $PHP -C -n -q $INCARG -d output_buffering=1 -d safe_mode=0 …

这行代码里面的 -n 参数表示不加载PHP的配置文件 php.ini ,因此 pcre.so 就不会被加载而导致错误,
,你只要改一下这行代码,去掉 -n 参数即可搞定。

Category: PHP / Zend  Tags:  3 Comments

三道PHP面试题

有三道PHP的面试题,除了第三题需要一些经验和对HTTP协议理解外,前面两题其实很简单,但是很少遇到有人答正确的,大部分人我想都不是技术问题,而是思考是否严谨的问题。

1. 下面语句输出什么?为什么?
if ($a=$b)  printf(“a==b”);
else  printf(“a!=b”);
2. $array[‘anykey’]和$array[anykey]有什么区别?
3. 写出使用telnet命令通过GET的方式访问http://www.toplee.com/index.php 得到页面返回的方法(不是用PHP实现,用dos或者unix命令行实现)。
Category: PHP / Zend  Tags:  25 Comments

验证码图片升级

想当初6.cn用一种开放的心态看待互联网,希望大家在一种友好、整洁的环境下共同发展,也希望让用户用起来更简单方便,一直不在任何地方提供“常见”的验证码,从去年开始,频繁开始受到各种恶意的攻击和注册,于是迫不得已加入第一个版本的验证码图片,那是一个简单、易辨认的图片 PHP验证码图片

昨天6.cn的验证码被攻破,于是迫不得以,又对验证码进行了升级,这次仍然首先考虑的是用户体验,让用户更容易辨认,想想google、qq等网站的验证码,真的是大多数时间我都是靠猜的,别说机器辨认了,人都很难,这次6.cn的验证码图片加入了更多干扰元素,背景颜色和干扰的曲线都是随机产生的,但总的来说还是比较好辨认 PHP验证码第二版 (实在看不清,可以刷新页面更新)

互联网就是这样,没有什么干净的东西可以独善其身。