作为一个已经工作很久的PHP程序员,对于PHP各种框架以及实现原理已经摸的很熟悉了,我之前是做java开发的,一直保留了java的开发思想,并且工作中也还在使用javaweb写项目,也使用比较成熟的IOC,AOP思想写了PHP框架,但是总感觉还是不够太了解PHP,于是有去了解了CGI,FastCGI,PHP-FPM,PHP-CGI,了解了他们的工作原理感觉还是不够,又去熟悉PHP与apache,nginx如何工作的其实就靠了个sapi进行来回工作,即使这样感觉还是不太了解PHP,当时做java的时候我经常去研究jvm里面是怎么工作的,所以PHP我感觉我也要去读下源码,毕竟PHP的源码是C写的,还是比较容易接受,于是就下载了PHP的源码开始阅读。 Day .No1 读取源码需要了解PHP的源码结构,PHP的源码结构比较清晰:
|_ ext php一些扩展存放目录 |_main PHP的一些内建函数 |_pear |_sapi spai 提供了一个和外部通信的接口与apache,nginx进行协同工作 |_tests php的一些demo |_TSRM |_Zend zend虚拟的实现
先从zend文件夹开始阅读 1.php的基本类型在C里面是如何实现的? 找到zend文件夹下面有一个头文件zend_types.h
typedef struct_zval_struct zval;
typedef struct_zend_class_entry zend_class_entry;
typedef struct_zend_refcounted zend_refcounted;
typedef struct_zend_string zend_string;
typedef struct_zend_array zend_array;
typedef struct_zend_object zend_object;

上面这些就是我们平常使用到的,对象,数组,变量,还有gc的结构体定义,看了之后发现PHP里面的任何类型都是C里面的一个结构体(struct)
typedef union _zend_value {
    zend_long lval;             /* long value */
    double dval;             /* double value */
    zend_refcounted *counted;
    zend_string *str;
    zend_array *arr;
    zend_object *obj;
    zend_resource *res;
    zend_reference *ref;
    zend_ast_ref *ast;
    zval *zv;
    void *ptr;
    zend_class_entry *ce;
    zend_function *func;
    struct {
        uint32_t w1;
        uint32_t w2;
    } ww;
} zend_value;

zend内部针对php的操作类型定义了一个union类型 我对C语言只是在学校期间学过简单语法,于是在看代码过程又学习这些语法什么意思。
typedef 意思是定义一个类型的别名 例子:
#include <stdio.h>
void main()
{
typedef int Integer;
Integer x=1;
Integer y=2;
printf("sum= %d",x+y);
}

typedef 我理解起来就是为了方便我们写代码的习惯,我熟悉java习惯了Integer 所以可以定义别名,提高写代码的效率。 struct 是C语言里面的结构体
#include <stdio.h>

typedef struct person{
char name[20];
int age;
}p;
void main()
{
p per;
per.name[4] = "gxx";
per.age = 12;
printf("姓名:%s,年龄:%d",per.name,per.age);
}

上面就是C语言里面的结构体定义以及对成员赋值,有点像我们平常使用的对象定义一些属性,并进行赋值。
ext文件夹下面存放的是php的扩展,里面有一个标准扩展 standard 文件夹,下面找到array.c文件是具体array里面方法操作的实现,找到php_array.h文件
PHP_FUNCTION(ksort);
PHP_FUNCTION(krsort);
PHP_FUNCTION(natsort);
PHP_FUNCTION(natcasesort);
PHP_FUNCTION(asort);
PHP_FUNCTION(arsort);
PHP_FUNCTION(sort);
PHP_FUNCTION(rsort);
PHP_FUNCTION(usort);
PHP_FUNCTION(uasort);
PHP_FUNCTION(uksort);列举一部分,就是定义的PHP里面的方法。

staticvoidphp_splice(HashTable*in_hash, zend_long offset, zend_long length, HashTable*replace, HashTable*removed)/* {{{ */
{
    HashTable    out_hash;
}

其实c语言针对php数组的操作是使用hashtable实现的。
PHP_FUNCTION(krsort)
{
    zval*array;
    zend_long sort_type= PHP_SORT_REGULAR;
    compare_func_t cmp;

    ZEND_PARSE_PARAMETERS_START(1,2)
        Z_PARAM_ARRAY_EX(array,0,1)
        Z_PARAM_OPTIONAL
        Z_PARAM_LONG(sort_type)
    ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);

    cmp=php_get_key_compare_func(sort_type,1);

    if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0)== FAILURE) {
        RETURN_FALSE;
    }
    RETURN_TRUE;
}

在zend文件夹下面的zend_hash.h文件里面 就能找到 #definezend_hash_sort(ht, compare_func, renumber)宏定义 所以数组的操作都是hashtable实现的。
阅读的过程发现了一个do {...}while(0)的用法挺好奇的就查了下什么含义。 例子: #define DOSOMETHING()\ foo1();\ foo2(); 调用 if(a>0) DOSOMETHING() 宏的预处理会直接被展开 if(a>0)   foo1(); foo2();



所以不是我们预期想要的结果。 我们这样定义之后再执行结果 #define DOSOMETHING() \ do{ \ foo1();\ foo2();\ }while(0)\



执行:
if(a>0)
{ 
  foo1(); 
  foo2();
};

这才是我们想要的结果。

更多推荐

PHP源码阅读 Day.1,源码目录结构分析