PHP源代码分析之HashTable

PHPzval结构体可以看出PHP使用HashTable来保存数组信息,PHP的HashTable使用了一些技巧,这些技巧是PHP高效数组操作的直接原因,源代码在PHP源代码目录的Zend/zend_hash.h  Zend/zend_hash.c 中。先来看看Zend HashTable的定义:

(全文…)

PHP源代码分析之变量

PHP中所有变量都使用zval结构体来存放:

 

PHP中可以使用函数 debug_zval_dump($var)查看变量的引用信息。

 相对于PHP的内核而已,我们编写的PHP代码都属于“用户空间”(user space),用户空间中的任何PHP变量都是由两部分组成:变量名(label)和变量值,从上面已经看到变量值存放在zval结构体中,那么变量名是放在哪里的呢? 下篇将继续分析PHP的HashTable结构体。

说明:本文中的图片均截自Marcus BörgerWez, FurlongSara, Golemon 三人的PHP ENTENSION WRITING (OSCON 2007)

PHP 5.2.6中源码稍有不同,不过含义一样,无关大雅。

 

refcount用来表示有多少个变量指向本结构体,is_ref用来标示是否是引用。看两个例子:

$a = 5;

$b = $a;

$b = 10;

 

$a = 5   =>  value.lval = 5, refcount = 1, type = IS_LONG, is_ref = 0

$b = $a  =>  value.lval = 5, refcount = 2, type = IS_LONG, is_ref = 0

$b = 10  =>  1  value.lval = 5, refcount = 1, type = IS_LONG, is_ref = 0   $a

             2  value.lval = 10, refcount = 1, type = IS_LONG, is_ref = 0   $b

 

在第三步时,PHP又产生了一个新的结构体用于保存变量$b, 原因在于原来$b指向的结构体的is_ref 成员的值为0. 这就是PHPCopy on Write机制。

 

再看下一种情况:

 

$a = 123;

$b = &$a;

$b = 456;

 

则按下图保存

PHP源代码分析之PHP生命周期

无论PHP通过何种方式启动,其初始化、响应单个请求、代码编译运行、结束请求、卸载过程都是相同的。

 

1.进程初始化

在模块的MINIT过程中可以添加你自定义的常量、变量、类、资源、流以及Filter句柄等等。

2.接受请求

 

3.解析编译运行代码

Zend Engine首先将代码编译成Zend Opcode,然后再使用Zend虚拟机来解释执行。

4.请求结束

5.进程退出

 

 

PHP中memcache扩展set失败的解决

在代码中遇到了memcache set方法失败的问题,无任何错误提示,PHP的memcache扩展本身也没有debug或者error提示。同样的代码,将本地的环境跟服务器的环境对比了一下(在服务器端一直没有遇到这个问题),发现原来是我所使用的php memcache扩展版本较低导致的。PECL有个bug报告http://pecl.php.net/bugs/bug.php?id=9486 ,也是提到这个问题了,在新的版本中已经解决了(2.1.1)。

使用php的memcache扩展时,如果给set/get方法传递一个空值(NULL),则会导致memcached服务端主动关闭连接,见如下的代码示范:
 

$mem new Memcache();

$mem->connect(’192.168.64.12′’11211′);

$mem->set(‘aaa’array(‘aaa’)); //成功

$mem->set($aaaa‘aaaa’); //失败,并导致到memcached服务器的连接丢失,所以之后的方法都失败了(返回false)

$mem->set(‘bbb’array(‘bbb’));//失败

$mem->get(‘aaa’);//失败

没有测试memcached扩展是否有过这样的bug。
顺便提一下在PHP中memcached和memcache是两个不同的扩展,区别是memcached基于libmemcached库封装的API接口。见PHP手册
This extension uses libmemcached library to provide API for communicating with memcached servers. It also provides a session handler (memcached).

而通常所说的memcached就是指memcached服务器端。

另外如果key过长(250以上),value过大(1M以上)或者过期时间过长(大于2592000)都会导致set失败。

第一次工作月总结

工作已经两个月, 有一些汗水, 有一些收获, 有一些欢乐, 有一些郁闷. 前方的路依然光明, 我要继续走下去.

整理一下两个月的收获和问题,说的不全,完全以这段时间的实践为主线。

一 面向对象 VS 面向过程
1.我们的选择
项目开始时,技术经理那边决定使用面向过程作为我们的主要开发方式,当时主要的考虑点是效率和项目人员对OO和面向过程的熟悉程度。
我们的项目是一个交易平台,预计并发、高负载、快速响应会是项目最重要的问题,再结合PHP本身的特点,我们觉得面向过程应该是我们的更好选择。
另外,项目中,除了我本人接触的OO较多外,其他人对于OO的理解还仅仅位于“对象”上, 对OOA/OOD/Design Pattern等基本无概念,而由于我们的时间和现有资源的问题,我们也不可能进行这方面的入职培训。 所以最终我们决定使用面向过程。

2.如何选择
很多人大谈OO或者面向过程的好处,互相攻击对方的方法缺陷。就讨论本身而言,辩论有利于更好的交流以及对知识更深层次的理解。但也容易带来一些偏见,这些往往是由于个人的阅历经验、对新事物的心态以及是否辩证看待事物有关。每个人的工作环境、项目要求等等都不尽相同,而OO和面向过程都不是万能的解决方案,他们有各自的优缺点,有各自的适应环境(所以不能一概而论, 不能断定哪种方式绝对的好),同时也有重叠的部分(既然有重叠,那么在某些情况下使用OO和面向过程皆可,具体使用哪一种,主要取决于个人的偏好)。
因而我们讨论两种方法,重点在于分析他们各自的利弊、适应环境,而不是打败对方。我们的目的在于赢得真理, 而不是赢得讨论。无论枪有多好,刀也不会淘汰;同时枪也的确比刀强大很多—某些情况下。 (全文…)

PHP单例模式的必要性

  多数人都是从单例模式的字面上的意思来理解它的用途, 认为这是对系统资源的节省, 可以避免重复实例化, 是一种"计划生育".  而PHP每次执行完页面都是会从内存中清理掉所有的资源. 因而PHP中的单例实际每次运行都是需要重新实例化的, 这样就失去了单例重复实例化的意义了. 单单从这个方面来说, PHP的单例的确有点让各位失望. 但是单例仅仅只有这个功能和应用吗? 答案是否定的,我们一起来看看.

1.
php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 在使用面向对象的方式开发时(废话), 如果使用单例模式, 则可以避免大量的new 操作消耗的资源.

2.
如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看zend Framework的FrontController部分.

3.
在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志.避免到处var_dump, echo.

upload.class.php的一点改进

/**
*
* @version $Id: upload.class.php,v 1.4 2007/04/27 00:52 xm.zhuge Exp $
* @copyright (c) 2007 Nandou Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/

*优化了结果信息提示
*更改了默认构造函数的实现,方便参数传递
+增加文件保存路径统计,文件上传数目统计

代码下载

NdUpload套件1.0.1

NdUpload套件包含两个文件:NdUpload.php和NdUploadForm.php,分别是文件上传类和表单生成类。

更新日志:
2007-04-11 20:40 , v 1.0.1
*改进了文件类型识别方式

代码下载

Pages: 1 2 下一页