Press "Enter" to skip to content

深入理解PHP之require/include顺序

在大型的Web项目中, include_path是一个模块化设计的根本中的根本(当然,现在也有很多基于autoload的设计, 这个不影响本文的探讨), 但是正是因为include_path, 经常会让我们遇到一些因为没有找到正确的文件而导致的看似”诡异”的问题.

也就有了如下的疑问:

include_path是怎么起作用的?

如果有多个include_path顺序是怎么样的?

什么情况下include_path不起作用?

Filed in PHP应用, PHP源码分析
with 34 Comments

深入理解SET NAMES和mysql(i)_set_charset的区别

最近公司组织了个PHP安全编程的培训, 其中涉及到一部分关于Mysql的”SET NAMES”和mysql_set_charset (mysqli_set_charset)的内容:

说到, 尽量使用mysqli_set_charset而不是”SET NAMES”, 当然, 这个内容在PHP手册中也有叙及, 但是却没有解释为什么.

最近有好几个朋友问我这个问题, 到底为什么?

问的人多了, 我也就觉得可以写篇blog, 专门介绍下这部分的内容了.

Filed in MySQL/PostgreSQL, PHP源码分析
with 30 Comments

Apache2中俩种设置PHP的异同

Apache2开始引入了Hook方式, 对应的在PHP中也提供了apache2handler这种sapi.

和我之前介绍过的PHP lifecycle不同, 这种情况下的PHP, 通过注册handler钩子, 从而可以在handler hook阶段有机会处理请求, 通过判断请求的handler, 来确定是否需要处理, 如果需要就会调用自身的处理器.

那么, 这种情况下也就有了多种配置方法, 主要考虑如下俩种方式…

Filed in PHP源码分析
with 2 Comments

一个想当然造成的错误(赋值语句的返回值)

一个想当然造成的错误.

需求是这样的, 我需要给一个二进制流加入一个签名串. 那么首先, 理所当然我的写了一个签名函数, 考虑到要判断签名操作是否成功, 所以我采用了传引用:

function sign(&$carrier, $fingerprint) {
	if (NULL === $fingerprint) {
		return FALSE;
	}
	//加入签名
	$carrier = 签名逻辑.
	return TRUE;
}

接下来, 考虑到, 如果签名失败, 那还是使用原来的字符串做为结果, 所以, 我想当然的写下了如下的代码….

Filed in PHP应用, PHP源码分析
with 13 Comments

深入理解PHP原理之变量生命期(一)

对于PHP的中的数据来源, 不外乎有俩种:

1. 来自代码中
2. 来自外部(GET/POST/DB)

对于代码中的变量(也就是直接量)来说, 变量分配/赋值在编译期, 活跃在执行器, 在请求关闭期被销毁.对于这些变量来说, 使用APC进行Opcode缓存, 则会缓存这部分变量的值.

而对于来自外部的变量, 变量分配/赋值在编译器后, 执行期前, 在请求关闭期被销毁,对于这些变量来说, 使用APC进行OpCode缓存, 是不会被缓存的.

今天就着重关注下外部变量的一个部分,GET来的数据的整个生命周期….

Filed in PHP源码分析
with 20 Comments

PHP5.2.x + APC的一个bug的定位

昨天环境迁移, 脚本出core, 因为之前的环境上运行正常, 所以初步认为是环境问题. 通过对core文件的分析, 初步发现原因和spl_autoload相关, backtrace如下:

#0  zif_spl_autoload (ht=Variable "ht" is not available.)
at /home/huixinchen/package/php-5.2.11/ext/spl/php_spl.c:310
310   if (active_opline->opcode != ZEND_FETCH_CLASS) {

(gdb) bt
#0  zif_spl_autoload (ht=Variable "ht" is not available.
	) at /home/huixinchen/package/php-5.2.11/ext/spl/php_spl.c:310
#1  0x00000000006a5da5 in zend_call_function (fci=0x7fbfffc100,
		fci_cache=Variable "fci_cache" is not available.)
at /home/huixinchen/package/php-5.2.11/Zend/zend_execute_API.c:1052
.....

脚本很简单, 通过session_set_save_handler注册了一个类为session的user handler.

去掉spl_autoload以后, 不出core了, 但是每次都会抛出Class not found的异常, 可见core确实和spl_autoload有关, 但是这个Class ** not found的fatal error问题又和什么相关呢, 这个fatal error是否是导致spl_autoload core 的直接原因呢?

代码本身并没有任何问题, 对环境做了对比以后, 初步认定为新环境启用了APC的缘故.

在bug.php中找到了有人报告类似的bug(spl_autoload crashes when called in write function of custom sessionSaveHandler), 但没有任何一个人给出原因,或者解决的办法.

看来, 只能自己分析了….

Filed in PHP源码分析
with 17 Comments

memory_limit的一个bug

PHP 5.2x中, 由于错误的选用了zend_atoi, 导致memory_limit不能设置为超过4G的值.

今天同事分享给我一个问题(thans to yanmi), 一段代码(PHP 5.2.11 Linux/X86_64),设置memory_limit为4096M会导致内存耗尽, 而设置4095M就不会. 奇怪的问题呵.

那是怎么回事呢?

Filed in PHP源码分析
with 8 Comments

提升PHP性能之改变Zend引擎分发方式

从PHP5.1开始,PHP提供了用户对Zend VM执行分发方式的选择接口.

之前的文章中, 我也提过这方面的内容, Zend虚拟机在执行的时候, 对于编译生成的op_array中的每一条opline的opcode都会分发到相应的处理器(zend_vm_def.h定义)执行, 而按照分发的方式不同, 分发过程可以分为CALL, SWITCH, 和GOTO三种类型.

默认是CALL方式, 也就是所有的opcode处理器都定义为函数, 然后虚拟机调用. 这种方式是传统的方式, 也一般被认为是最稳定的方式.

SWITCH方式和GOTO方式则和其命名的意义相同, 分别通过switch和goto来分发.官方给出的描述说GOTO方式最快.

那么如果使用GOTO方式, 效率上到底能提高多少呢? 今天我就分别使用各种方式来测试一番:

Filed in PHP应用, PHP源码分析
with 12 Comments

PHP文件上传源码分析(RFC1867)

文件上传,一般分为俩种方式FTP和HTTP, 对于我们的互联网应用来说: FTP上传虽然传输稳定, 但是易用性和安全性都是个问题. 你总不至于在用户要上传头像的时候告诉用户”请打开FTP客户端,上传文件到http://www.laruence.com/uploads/中, 并以2dk433423l.jpg命名”吧?

而基于HTTP的上传,相对来说易用性和安全性上就比FTP要增强了很多. 可以应用的上传方式有PUT, WEBDAV, 和RFC1867三种, 本文将分析在PHP中,是如何基于RFC1867实现文件上传的.

Filed in PHP应用, PHP源码分析
with 20 Comments