Tag Archives: php

php shell

本文要讲的php shell并非是使用php来写shell脚本,而是讲一个php的REPL的交互式shell。所谓REPL,也就是read-eval-print-loop,也就是说,shell读入一个指令,计算,然后输出结果,常见的有Python、Ruby的IRB等。
对于PHP,我们常常会写一个test.php,然后放入一些自己的代码,再打开浏览器检验一下,如果不对,又要重新修改代码,非常麻烦。交互式shell的好处就可以体现出来了,输入指令之后可以立刻看到执行代码的结果,所以非常适合用来检验代码片段(snippets)的正确性以及进行一些试验。
PHP本身自带一个交互式的shell,在命令行中输入php -i,便可以交互式运行,但要先输入一个php脚本的起始标签,但是该shell遇到异常的时候会直接退出,非常不方便。那么我找到一个非常接近于REPL的交互式shell便是php-shell

1. 安装
php-shell要求php 5.0以上版本
下载PHP_Shell-0.3.1.tgz
运行pear install PHP_Shell-0.3.1.tgz
如果确保pear已经安装,并在你的PATH路径中
2. 使用方法
在命令行下输入php-shell(Linux为php-shell.sh)进入交互式命令行:

PHP-Shell – Version 0.3.1, with readline() support
(c) 2006, Jan Kneschke <jan@kneschke.de>

>> use ‘?’ to open the inline help

>>

这时候我们可以输入我们所需的表达式了,在php-shell中直接输入变量名,它也可以将内容直接打印出来:
>> $a = new ArrayObject( )
ArrayObject::__set_state(array(
))
>> $a->
__construct(
append(
count(
exchangeArray(
getArrayCopy(
getFlags(
getIterator(
getIteratorClass(
offsetExists(
offsetGet(
offsetSet(
offsetUnset(
setFlags(
setIteratorClass(
>> $a->append( ‘a’ )

>> $a->count( )
1
>> $a->offsetGet( 0 )
‘a’
当出现异常时,php-shell也会打印出异常的内容。
你可以使用exit退出。
3. Tab补全
php-shell一个强大的功能是支持补全,以下内容可以被补全:

new 类名()
类名::方法名()
类名::常量名
$变量名
函数名()
$object->方法名()

请先输入第一个字符然后按TAB按钮。如果只有一种匹配,它便会直接补全名称,否则,再按一次TAB会列出所有的可能性。
如果你想查看所有已声明的类,你可以使用 getdeclaredclasses():
>> get_<TAB>
>> get_<TAB><TAB>
get_browser(

get_declared_classes(

get_resource_type(
>> get_dec<TAB>
>> get_declared_<TAB><TAB>
get_declared_classes(
get_declared_interfaces(
get_defined_constants(
get_defined_functions(
get_defined_vars(
>> get_declared_classes( )

4. 总结
如果是php新手,希望php-shell能帮你快速掌握php。老手也可以用其来检验代码段。
除此之外,也可以尝试一下基于Web页面的php shell,如http://phpshell.sf.net/

PHP的二进制位移操作

PHP主要是设计于文本操作的,其实PHP不适合做数学运算,效率也不高,不过因为这次的项目中有个东西必须使用到二进制位移操作,在PHP上面遇到了一些麻烦。
因为PHP只有32位有符号整数,没有64位长整型,也没有无符号整数。其整型的范围是-231-1~231,超出这个范围的,将被解释为浮点数。因此,0xFFFFFFFF,直接打印,显示的是4294967295,及232:

>> 0xFFFFFFFFF
4294967295
>> gettype(0xFFFFFFFF)
‘double’

而在32位有符号整型中,0xFFFFFFFF应表示-1:
>> (int)0xFFFFFFFFF
-1

而PHP不支持浮点数的二进制位移操作,如果要进行,会先转换为整型,最后的结果,也将按照整型来返回:

>> 1 << 31
-2147483648
>> 1 << 30
1073741824
>> 1 << 32
1
>> 0xFFFFFFFF >> 1
-1
同时PHP的向右位移操作,高位会填充符号位,而且PHP没有提供类似Java的>>>来强制填充0:

>> 1 << 32
1
>> 0xFFFFFFFF >> 1
-1
>> 0xFFFFFFFF >> 2
-1
>> 0xFFFFFFFF >> 3
-1
>> 0xFFFFFFFF >> 31
-1

如何解决这个问题呢,我考虑过使用BCMath数学函数库,直接处理字符串表示的整数,或者是GMP/BigInt扩展等。不过我想既然使用字符串,那么我可以字符串地彻底一些,把数字转换成32个二进制的字符串,再手工填充0,最后转换回来。
不知道哪位有更好的方法,请告诉我。
代码如下:
直接下载代码:shift.php
(另外,其实代码可以扩展为任意位2进制的位移操作,这里我没有做)

<?php
/**
* 无符号32位右移
* @param mixed $x 要进行操作的数字,如果是字符串,必须是十进制形式
* @param string $bits 右移位数
* @return mixed 结果,如果超出整型范围将返回浮点数
*/
function shr32($x, $bits){
[...]

Nginx的WordPress配置

WordPress是一个非常流行的Blog系统,它可以利用Apache的mod_rewrite来实现URL的静态化。安装好的WordPress在配置了持久链接之后,会在网站的根目录下(如果可写)生成一个.htaccess文件,这个文件可以指示Apache如何进行URL重写(如果服务器配置为允许使用htaccess的指令的话),它的内容如下:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

这个文件的意思就是,如果当请求的文件不存在,那么把请求内部重定向到/index.php。WordPress会自己分析请求的URL,来判断显示哪个页面。
在上次配置了Nginx+PHP之后,由于Nginx不支持Apache的.htaccess文件,要实现持久连接静态化,我们必须手工配置Nginx的文件。首先找到Nginx的配置文件,默认编译后的配置文件在/usr/local/nginx/conf/nginx.conf;Ubuntu通过包安装的配置文件位于/etc/nginx/nginx.conf,也可以编辑vhost的配置文件,放在了/etc/nginx/sites-available下。
以下是基本的配置(Ubuntu下的范例):
location / {
index index.html index.php;
if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
[...]

Linux 上配置 Nginx + PHP5 FastCGI

Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,以事件驱动的方式编写,所以有非常好的性能,同时也是一个非常高效的反向代理、负载平衡。其拥有匹配Lighttpd的性能,同时还没有Lighttpd的内存泄漏问题,而且Lighttpd的mod_proxy也有一些问题并且很久没有更新。
因此我打算用其替代Apache应用于Linux服务器上。但是Nginx并不支持cgi方式运行,原因是可以减少因此带来的一些程序上的漏洞。那么我们必须使用FastCGI方式来执行PHP程序。
下面是我成功地配置Nginx + PHP5 FastCGI的过程

PHP4.4.6和Mysql 5.0兼容性

这次有台Windows服务器拿到手中,需要装AMP,我一激进,装了Apache2.2.4 + Php5.2.1 + mysql-5.0.37。事后发现,网站程序用PHP4写的,和PHP5.2.1有点兼容性问题,于是乎换装PHP4,发现PHP4没有Apache2.2的模块,只好用CGI方式安装。接下来程序运行报错数据库无法连接,猜测是php4的mysql扩展不兼容mysql5。在网上找了半天,发现有老外自己编译了一个php4.4.6的补丁,下载覆盖了原来的dll文件,然后便成功了,特此备忘。

老外文章的地址: http://edin.dk/plugin/tag/php4+mysql5+windows+build
补丁下载地址:php-4.4.6-w-mysql-5.0.37.zip

Paypal IPN接口开发小结

最近终于搞定了该死的Paypal ipn,特地在此留下点东西备忘。
所谓paypal ipn(Instant Payment Notification),就是Paypal开发的一种能主动通知第三方卖家系统交易状态的一种机制。IPN的原理很简单,就是当产生了一个交易之后,交易状态发生变化时,如用户已经付款、或者退款、撤销时,Paypal利用常用的HTTP POST方式,将交易的一些变量提交给网站的某个页面(称之为IPN Handler),当这个页面接受到请求时候,将这些数据原封不动加上一个指示验证的cmd=_notify-validate,POST回Paypal的接口地址,如果数据正确,那么Paypal返回字符串VERIFIED,否则为INVALID,如果结果为VERIFIED,那么你的程序就可以使用这些数据进行操作。
但代码的调试是一件很痛苦的事情,因为作为第三方开发人员,不可能开两个帐号,每次测试还要之间交易一些钱,所以Paypal专门开发了Sandbox给开发人员进行开发,首先到https://developer.paypal.com/ 注册一个开发帐号,好了之后再进入Sandbox建立测试用的Paypal虚拟帐号(至少应该建立一个Business的和一个Personal的),这种账号注册方法和Paypal的流程一样,信息可以是假的,包括银行帐号、信用卡(其实Paypal Sandbox会自动生成一些随机的号码)。接下来需要激活Paypal Sandbox的虚拟帐号,注意,这里不管你在Paypal Sanbox注册时填什么邮件地址,有任何发送到虚拟帐号所填邮箱的邮件都存会在开发帐号的管理界面中的Email页(导航栏上有)中。登录Sandbox的虚拟Paypal环境,还需要验证虚拟帐号的银行,这里可以随便填,然后通过Add Funds来给账户充值(想填多少填多少)。然后,还需要激活IPN的选项,在Business的那个账户的Profile设置页面中,点击,然后点击Edit按钮,打开IPN,这里如果你使用的是固定的IPN Handle,可以直接将地址填入。
接下来,我们测试的时候,应该将Paypal接口的地址设置为https://www.sandbox.paypal.com/cgi-bin/webscr
最后基本的流程为:

用户在我们的网站上选择商品、放入购物车,然后检查准备支付
网站根据购物车中的商品,生成Paypal的支付表单(也是提交到上面IPN用的Paypal接口地址),包含了此次交易的一些信息(下次会专门找机会解释一下)。并在自己的数据库中生成一张订单记录。
Paypal在Session中记录下这些交易信息
用户用Paypal账户登录Paypal(Sandbox用Sandbox的虚拟帐号),复查明细,点击Pay按钮
Paypal进行交易处理,如果我们的Paypal收款帐号在接受帐款上没有什么问题(没有特别的需要在界面上“Accept”的地方),交易完成,那么Paypal会发送一个IPN,并发送提示邮件。
我们IPN Handler接受到信息,首先向Paypal进行校验,如果信息正确,然后根据信息和自己数据库中进行比对,如果无误,可以将支付信息保存,并修改订单状态。
然后Paypal会显示一个界面表示交易完成,此时如果用户点击“Return”按钮,Paypal会将用户送回我们网站指定地点。
我们网站迎接用户回来,向用户表示感谢,并进行提醒,给出订单号等等。

整个流程基本如下,不过其中有很多要注意的地方:

我们看到了,接口地址是https开头的,也就是要求使用SSL进行连接,其实Paypal Sandbox可以使用http,但是最后实际的Paypal接口,不支持http协议,所以如果你用PHP写IPN Handler脚本的话,在验证信息的代码部分,如果简简单单使用fopen、HTTP_Request之类的工具是没用的,PHP的socks库不支持SSL,应该使用curl,有两种方法,一个是使用PHP扩展中的libcurl,Paypal官方发布的SDK中便是使用的这个方法,但Paypal的SDK非常复杂,如果想自己写,可以使用Snoopy,一个简单实用的PHP请求库(它自己说是模拟了浏览器的行为),而它使用的是Curl的可执行文件,通过管道获得结果,而非php的libcurl,所以自己cURL的主页上下载一个支持SSL的编译版本,可能还需要安装OpenSSL,不过对于Linux系统,可能应该会都带。
在支付表单中,可以自己设置notify_url字段,来指定此次交易的信息应该发送到哪个地方,这样就可以覆盖在Profile中我们的设置,另外,这个字段要进行urlencode。
我们得到的IPN信息中,status对应的便是交易状态,如Complete表示完成,首字母大写,而验证结果则是VERIFIEY或者INVALID,全部大写,具体的内容,可以查看Paypal官方的文档订单管理整合指南。

Cache_Lite的检测缓存失效

PEAR组件Cache_Lite是一个很实用的文件缓存组件,我在PHP编程中常常用到,现在我常需要检测某个id的缓存是否已经失效了,而Cache_Lite本身并未提供这样的功能,因此我写了这样一个函数:

function isExpired(&$cache, $id, $group = ‘default’){
$cache->_setFileName($id, $group);
return !file_exists($cache->_file) ||
filemtime($cache->_file) < (time() - $cache->_lifeTime));
}

使用也很简单,应该一眼就能看明白。当然也可以通过继承Cache_Lite,并添加一个方法来完成。

Zend Framework 指南

作者:Chris Shiflett翻译:ShiningRay
我们邀请了PHP安全专家——兼最新发布的Zend Framework的贡献者——Chris Shiflett来为我们写一篇关于ZF主要特点的文章。
这份完整的、按部就班的教程通过向你展示如何应用框架写出一个简单的新闻管理系统,为你提供了构建实际应用的独特视角。
Zend Framework终于掀开了其神秘的面纱!尽管它尚处于开发过程的早期阶段,但本文将现在所能用的中最好的部分特别呈现给读者,并通过构建一个简单的应用这个过程引导你了解这个框架。
Zend很早就发布了框架并引入社区运作。写本指南只能针对框架今天的情况来列出其特点。因为本指南是在线发布的,所以我会在框架发生变化的时候及时更新本文,这样就能尽可能保持一致。
要求
Zend Framework 要求使用 PHP 5。为了能完全利用本指南中展示的代码,你还需要Apache Web服务器,因为范例应用(一个新闻管理系统)用到了mod_rewrite。
本指南中的代码可以自由下载,所以你可以亲自尝试一下。可以从Brain Bulb的网站上下载到:http://brainbulb.com/zend-framework-tutorial.tar.gz.
下载框架
在开始阅读本指南之前,你还需要先下载一份框架的预览发布版。可以用浏览器察看 http://framework.zend.com/download 并选择 tar.gz 或者 zip 文件手工下载,也可以使用下面的命令行:
清单1
$ wget http://framework.zend.com/download/tgz
$ tar -xvzf ZendFramework-0.1.2.tar.gz
注意
Zend已经计划提供一个独立的PEAR通道来方便下载。

下载了预览发布版之后,将这个库的目录放到一个方便的地方。在本教程中,我将库的目录名改称了lib,以便提供一个简单干净的目录结构:
清单2

app/
+-views/
+-controllers/
www/
+- .htaccess
+- index.php
lib/
www 目录是文档根目录,controllers和views目录为空,是将来要用的,lib目录是来自于下载的预览版。
入门
我第一个要向你展示的组件是Zend_Controller。在很多情况下,它为要开发的应用提供了一个基础,同时它也是令Zend Framework超越了组件集合的一个部分。不过在使用它之前,需要将所有进入的请求引导到某个PHP脚本中。本教程将使用mod_rewrite来完成这个目的。
如何用好mod_rewrite确实是一门艺术,不过还好本文中这个特殊的任务十分简单。如果你对mod_rewrite或者是Apache的一般配置还不是很熟悉的话,可以在文档根目录下创建一个.htaccess文件,并加入一下指令:
清单3
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
Zend_Controller目前的任务之一就是去掉对mod_rewrite的依赖。为了提供一个预览版可以使用的例子,本教程便使用了mod_rewrite。
如果你直接在httpd.conf中添加这些指令,还必须重新启动Web服务。但是,如果使用.htaccess文件,就不用了,而且这样更好。你可以随便在index.php中写点东西,然后任意请求某些路径来测试一下,比如/foo/bar。例如,如果你的主机是example.org,那么就请求URL http://example.org/foo/bar。
可能你还想在 include_path 中包含框架库的路径。你可以直接在php.ini中配置,或者可以将以下指令放入.htaccess文件中:
清单4
php_value include_path "/path/to/lib"
Zend
Zend 类包含了一系列十分通用也十分有用的静态方法。这是唯一一个需要手工进行包含的类:
清单5
<?php

include ‘Zend.php’;

?>
一旦引用了Zend.php,就可以访问Zend类中的所有方法了。使用loadClass()方法,载入其他类也变得简单了。例如载入Zend_Controller_Front类: [...]

什么是 Cake?

Cake 是一个针对PHP的,使用了诸如ActiveRecord、Association Data Mapping、Front Controller和MVC等知名设计模式的快速开发框架。我们的主要目标是提供一个可以令各种层次的PHP用户快速地开发出健壮的Web应用,而又不失弹性。
为什么使用 Cake?

灵活的许可证:MIT License

完全自主的知识产权:每一行代码都是由CakePHP开发小组写出来的。

极其简洁:只要看看名字就知道了……
快速开发:开发之迅速史无前例。(看看zZine的文章)

最佳实践:Cake很容易理解,而且已经把工业标准设置在了安全性、会话处理和其他的东西中。
面向对象: 无论你是一个老练的OO程序员还是一个初学者,都可以感到十分轻松。
无需配置:只要安装好数据库,好戏就开场了。

厌倦了不断重复?总是Ctrl-C然后Ctrl-V代码?想让你的应用更快速地转化成产品?请选择Cake!看看Wiki立刻上手。

关键特性

兼容 PHP4 和 PHP5
提供了集成的数据库 CRUD 和简化了的查询
请求分配器,和美观的、可自定义URL。
快速、灵活的模版机制(使用PHP语法和助手方法)
可以从任何网站的子目录中运行,只需要少量甚至无需改动Apache的配置。

立刻加入
我们一直在寻找人手来帮助我们写指导、进行测试和书写文档。参与的最佳地点就是IRC。我们正在完善一些针对希望对这个项目编写代码的贡献者指导方针。当然,任何人都可以提出您宝贵的意见和建议。
#cakephp at irc.freenode.net ? CakePHP Wiki ? CakePHP Google Group ? CakeTRAC (development site)
指南

Homepage

PHP 对比 PERL

本文是 http://tnx.nl/php – 如果你要复制他,请保持这个链接。
翻译:ShiningRay @Nirvana Studio
目录

参数和返回值极其矛盾
PHP对大小写不敏感的操作使用不同的函数
PHP的函数命名方式的不一致
PHP没有词法范围
PHP的主名空间中函数太多
PHP缺少抽象令 TIMTOWTDI 走向糟糕的极端
更多信息

参数和返回值极其矛盾
要展示这个问题,下面有一个函数列表,里面的函数用来匹配用户定义的内容:(也许甚至那些用PHP的人才会使用这个文档,只是用来查看该用哪个函数:P)

 
匹配
替换使用
大小写不敏感
返回的数字
数组参数
返回匹配
s/m/x标志
偏移(-1=结尾)

ereg
ereg
 

所有

数组

0

ereg_replace
ereg
字符串

所有



0

eregi
ereg
 

所有

数组

0

eregi_replace
ereg
字符串

所有



0

mb_ereg
ereg[1]
 

所有

数组

0

mb_ereg_replace
ereg[1]
字符串/表达式

所有



0

mb_eregi
ereg[1]
 

所有

数组

0

mb_eregi_replace
ereg[1]
字符串

所有



0

preg_match
preg[2]
 
皆可
一个

数组

0

preg_match_all
preg
 
皆可
所有

数组

0

preg_replace
preg
字符串/表达式
皆可
无/所有



0

str_replace
str
字符串

所有

数字

0

str_ireplace
str
字符串

所有

数字

0

strstr, strchr
str
 

一个

子串

0

stristr
str
 

一个

子串

0

strrchr
str
 

一个

子串

-1

strpos
str
 

一个

索引

n

stripos
str
 

一个

索引

n

strrpos
char[3]
 

一个

索引

n

strripos
str
 

一个

索引

-1

mb_strpos
str[1]
 

一个

索引

n

mb_strrpos
str[1]
 

一个

索引

-1

这种问题还存在在其他的函数组里,不仅仅是匹配的这部分而已。
(在Perl中,所有这些功能都可以通过四个简单的操作符来完成。)
[1] 用于处理多字节字符
[2] PCRE regex: 所谓的“Perl兼容”的正则表达式。
[3] 在PHP5中也是字符串str
PHP对大小写不敏感的操作使用不同的函数
(这个可能会有两方面的争论。有些人认为提供不同的函数更好,即使这意味着又要记很多名词了)
在Perl中,你可以使用两个lc() 或者是 /i 标志,而PHP通常会提供一个大小写敏感的变量。而且,大小写不敏感的那些版本的函数名的命名方式也不一致。

Perl:
$foo cmp $bar
lc $foo cmp lc $bar

PHP:
strcmp($foo, $bar)
strcasecmp($foo, $bar)

 
 
 

Perl:
index($foo, $bar)
index(lc $foo, lc $bar)

PHP:
strpos($foo, $bar)
stripos($foo, $bar)

 
 
 

Perl:
$foo =~ s/foo/bar/
$foo =~ s/foo/bar/i

PHP:
$foo = str_replace(‘foo’, ‘bar’, $foo)
$foo = str_ireplace(…)

PHP:
$foo = ereg_replace(‘foo’, ‘bar’ ,$foo)
$foo = [...]