php7扩展开发[11] MVC之路由解析和加载文件

原创
2016-06-23 13:09:30 901浏览

```
场景:想要用C实现PHP的一个MVC结构的路由解析和加载文件的功能,一共要解决几个问题
1.由于MVC要加载多个C文件,所以要修正config.m4,修改config.m4内容第十行左右,去掉dnl,
PHP_ARG_WITH(dora, for route support,
dnl Make sure that the comment is aligned:
[ --with-route Include dora support])
在下面追加到以下内容:
if test -z "$PHP_DEBUG" ; then
AC_ARG_ENABLE(debug, [--enable-debug compile with debugging system], [PHP_DEBUG=$enableval],[PHP_DEBUG=no] )
fi

最后一行,加载所需所有C文件,如下:
PHP_NEW_EXTENSION(dora, dora.c common/utilts.c loader/loader.c route/route.c controller/controller.c model/model.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
PHP_ADD_BUILD_DIR([$ext_builddir/common])
PHP_ADD_BUILD_DIR([$ext_builddir/loader])
PHP_ADD_BUILD_DIR([$ext_builddir/route])
PHP_ADD_BUILD_DIR([$ext_builddir/controller])
PHP_ADD_BUILD_DIR([$ext_builddir/model])

```
```c

#include "utilts.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "Zend/zend_list.h"
#include "Zend/zend_interfaces.h"

//执行PHP文件函数
int zend_execute_scripts_ext(char *filepath){

zval retval;

zend_file_handle zfd;
zfd.type = ZEND_HANDLE_FILENAME;
zfd.filename = filepath;
zfd.free_filename = 0;
zfd.opened_path = NULL;

//zend_execute_scripts(int type, zval *retval, int file_count, ...);
//FAILURE OR SUCCESS
return zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC,&retval,1,&zfd);



}


//调用类中的方法
int call_user_class_method(zval *retval, zend_class_entry *obj_ce,
zval *obj, zval func, uint32_t params_count, zval params[]){


HashTable *function_table;

if(obj) {
function_table = &Z_OBJCE_P(obj)->function_table;
}else{
function_table = (CG(function_table));
}

zend_fcall_info fci;
fci.size = sizeof(fci);
fci.function_table = function_table;
fci.object = obj ? Z_OBJ_P(obj) : NULL;;
fci.function_name = func;
fci.retval = retval;
fci.param_count = params_count;
fci.params = params;
fci.no_separation = 1;
fci.symbol_table = NULL;



//FAILURE OR SUCCESS
return zend_call_function(&fci, NULL TSRMLS_CC); //函数调用结束。

}


```
```c
3.修改php_route.h头文件内容

在第五十行左右,加入以下内容

//定义类
extern zend_class_entry *route_ce;
//定义loader类中的方法
PHP_METHOD(route_ce,__construct);
PHP_METHOD(route_ce,run);
```
```c
4.修改route.c文件内容

/**
* 声明构造函数
* @param
* @return
*/
ZEND_METHOD(route,__construct){


zval *app_dir;

if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &app_dir) == FAILURE )
{
RETURN_NULL();
}
//zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_length);
zend_update_static_property(route_ce, "app_dir", sizeof("app_dir")-1, app_dir TSRMLS_CC);

}



/**
* 加载view
* @param
* @return
*/
ZEND_METHOD(route,run){


zend_string* controller_name = zend_string_init("Index",strlen("Index"),0);
zend_string* action_name = zend_string_init("Index",strlen("Index"),0);

zval *c_result;
zval *a_result;
int flag;



//设置站点目录
zval *app_dir = zend_read_static_property(Z_OBJCE_P(getThis()), "app_dir", sizeof("app_dir")-1, 0 TSRMLS_DC);


//获取GET请求参数hashtable
zval *get_arr = &PG(http_globals)[TRACK_VARS_GET];
HashTable *ht= HASH_OF(get_arr);
//int array_count = zend_hash_num_elements(Z_ARRVAL_P(get_arr));


//获取controller_name
zend_string *c_key= zend_string_init("controller", sizeof("controller")-1, 0);

if ((c_result = zend_hash_find(ht, c_key)) != NULL) {

controller_name = zval_get_string(c_result);

}else{

zend_error_noreturn(E_CORE_ERROR, "Couldn't find controller param in url.");

}
//释放key的变量
zend_string_release(c_key);


//获取action_name
zend_string *a_key= zend_string_init("action", sizeof("action")-1, 0);

if ((a_result = zend_hash_find(ht, a_key)) != NULL) {

action_name = zval_get_string(a_result);
//php_printf("%s\n", Z_STRVAL_P(a_result));
//php_printf("%s\n", zval_get_string(a_result));
}else{

zend_error_noreturn(E_CORE_ERROR,"Couldn't find action param in url.");

}

//释放key的变量
zend_string_release(a_key);


//拼装controller文件路径
char *path = Z_STRVAL_P(app_dir);
char *c_2 = "controllers/";
strcat(path,c_2);

//zend_string->char *
char *c_3 = ZSTR_VAL(controller_name);
strcat(path,c_3);

char *c_4 = ".php";
strcat(path,c_4);

//php_printf("%s\n", c_1);
// php_printf("%s\n", controller_name);
// php_printf("%s\n", action_name);
//PHPWRITE(Z_STRVAL_P(app_dir), Z_STRLEN_P(app_dir));



//加载执行controller文件
flag = zend_execute_scripts_ext(c_1);

if(flag == FAILURE){

zend_error_noreturn(E_CORE_ERROR,"Couldn't find file: %s.",c_1);

}


//查找controller对应的
//zend_class_entry *zend_lookup_class(zend_string *name);
zend_class_entry *controller_ce = zend_lookup_class(controller_name);

if(controller_ce == NULL){

zend_error_noreturn(E_CORE_ERROR,"Couldn't find file: %s.",c_1);
}


zval obj;
object_init_ex(&obj, controller_ce);


zval function_name;
ZVAL_STRING(&function_name,ZSTR_VAL(action_name));


flag = call_user_class_method(return_value, controller_ce, &obj, function_name, 0, NULL);

if(flag == FAILURE){


zend_error_noreturn(E_CORE_ERROR,
"Couldn't find implementation for method %s%s%s",
controller_ce ? ZSTR_VAL(controller_ce->name) : "",
controller_ce ? "::" : "",
function_name);

}

//RETURN_ZVAL(get_arr, 1, 0);

}

const zend_function_entry route_functions[] = {


//注册route类中的方法
ZEND_ME(route, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
ZEND_ME(route,run,NULL,ZEND_ACC_PUBLIC)


PHP_FE_END /* Must be the last line in route_functions[] */
};

PHP_MINIT_FUNCTION(route)
{

//注册route类
zend_class_entry ce;

//define INIT_NS_CLASS_ENTRY(class_container, ns, class_name, functions)
INIT_NS_CLASS_ENTRY(ce,"Dora" ,"Route", route_functions);
route_ce = zend_register_internal_class(&ce TSRMLS_CC);

//声明一个静态数据成员app_dir
//zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type);
zend_declare_property_string(route_ce, "app_dir", strlen("app_dir"), "",ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_DC);


return SUCCESS;
}
```
```c
5.编译安装
phpize
./configure --with-php-config=/usr/bin/php-config
make && make install

```
```c
6.php7创建类所有到的知识点


常见的变量操作宏

CG -> Complier Global 编译时信息,包括函数表等(zend_globals_macros.h:32)
EG -> Executor Global 执行时信息(zend_globals_macros.h:43)
PG -> PHP Core Global 主要存储php.ini中的信息
SG -> SAPI Global SAPI信息

//===============================================================================
PHP7中的zval的类型:
/* regular data types */
define IS_UNDEF 0
define IS_NULL 1
define IS_FALSE 2
define IS_TRUE 3
define IS_LONG 4
define IS_DOUBLE 5
define IS_STRING 6
define IS_ARRAY 7
define IS_OBJECT 8
define IS_RESOURCE 9
define IS_REFERENCE 10

define IS_CONSTANT 11
define IS_CONSTANT_AST 12

define _IS_BOOL 13
define IS_CALLABLE 14

define IS_INDIRECT 15
define IS_PTR 17

//===============================================================================
PHP7中获取的zval赋值:
- ZVAL_STRING(zv, str, 1);
+ ZVAL_STRING(zv, str);
- ZVAL_STRINGL(zv, str, len, 1);
+ ZVAL_STRINGL(zv, str, len);
- ZVAL_STRING(zv, str, 0);
+ ZVAL_STRING(zv, str);
+ efree(str);
- ZVAL_STRINGL(zv, str, len, 0);
+ ZVAL_STRINGL(zv, str, len);

//===============================================================================

PHP7中获取的zval的值和长度:
define Z_LVAL(zval) (zval).value.lval
define Z_LVAL_P(zval_p) Z_LVAL(*(zval_p))

define Z_DVAL(zval) (zval).value.dval
define Z_DVAL_P(zval_p) Z_DVAL(*(zval_p))

define Z_STR(zval) (zval).value.str
define Z_STR_P(zval_p) Z_STR(*(zval_p))

define Z_STRVAL(zval) ZSTR_VAL(Z_STR(zval))
define Z_STRVAL_P(zval_p) Z_STRVAL(*(zval_p))

define Z_STRLEN(zval) ZSTR_LEN(Z_STR(zval))
define Z_STRLEN_P(zval_p) Z_STRLEN(*(zval_p))

define Z_STRHASH(zval) ZSTR_HASH(Z_STR(zval))
define Z_STRHASH_P(zval_p) Z_STRHASH(*(zval_p))

define Z_ARR(zval) (zval).value.arr
define Z_ARR_P(zval_p) Z_ARR(*(zval_p))

define Z_ARRVAL(zval) Z_ARR(zval)
define Z_ARRVAL_P(zval_p) Z_ARRVAL(*(zval_p))

define Z_OBJ(zval) (zval).value.obj
define Z_OBJ_P(zval_p) Z_OBJ(*(zval_p))

define Z_OBJ_HT(zval) Z_OBJ(zval)->handlers
define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*(zval_p))

define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf
define Z_OBJ_HANDLER_P(zv_p, hf) Z_OBJ_HANDLER(*(zv_p), hf)

define Z_OBJ_HANDLE(zval) (Z_OBJ((zval)))->handle
define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*(zval_p))

define Z_OBJCE(zval) (Z_OBJ(zval)->ce)
define Z_OBJCE_P(zval_p) Z_OBJCE(*(zval_p))

define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval))
define Z_OBJPROP_P(zval_p) Z_OBJPROP(*(zval_p))

define Z_OBJDEBUG(zval,tmp) (Z_OBJ_HANDLER((zval),get_debug_info)?Z_OBJ_HANDLER((zval),get_debug_info)(&(zval),&tmp):(tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL))
define Z_OBJDEBUG_P(zval_p,tmp) Z_OBJDEBUG(*(zval_p), tmp)

define Z_RES(zval) (zval).value.res
define Z_RES_P(zval_p) Z_RES(*zval_p)

define Z_RES_HANDLE(zval) Z_RES(zval)->handle
define Z_RES_HANDLE_P(zval_p) Z_RES_HANDLE(*zval_p)

define Z_RES_TYPE(zval) Z_RES(zval)->type
define Z_RES_TYPE_P(zval_p) Z_RES_TYPE(*zval_p)

define Z_RES_VAL(zval) Z_RES(zval)->ptr
define Z_RES_VAL_P(zval_p) Z_RES_VAL(*zval_p)

define Z_REF(zval) (zval).value.ref
define Z_REF_P(zval_p) Z_REF(*(zval_p))

define Z_REFVAL(zval) &Z_REF(zval)->val
define Z_REFVAL_P(zval_p) Z_REFVAL(*(zval_p))

define Z_AST(zval) (zval).value.ast
define Z_AST_P(zval_p) Z_AST(*(zval_p))

define Z_ASTVAL(zval) (zval).value.ast->ast
define Z_ASTVAL_P(zval_p) Z_ASTVAL(*(zval_p))

define Z_INDIRECT(zval) (zval).value.zv
define Z_INDIRECT_P(zval_p) Z_INDIRECT(*(zval_p))

define Z_CE(zval) (zval).value.ce
define Z_CE_P(zval_p) Z_CE(*(zval_p))

define Z_FUNC(zval) (zval).value.func
define Z_FUNC_P(zval_p) Z_FUNC(*(zval_p))

define Z_PTR(zval) (zval).value.ptr
define Z_PTR_P(zval_p) Z_PTR(*(zval_p))

//===============================================================================

php7 用来判断类型和取值

void display_value(zval zv,zval *zv_p,zval **zv_pp)
{
if( Z_TYPE(zv) == IS_NULL )
{
php_printf("类型是 IS_NULL!\n");
}

if( Z_TYPE_P(zv_p) == IS_LONG )
{
php_printf("类型是 IS_LONG,值是:%ld" , Z_LVAL_P(zv_p));
}

if(Z_TYPE_PP(zv_pp) == IS_DOUBLE )
{
php_printf("类型是 IS_DOUBLE,值是:%f" , Z_DVAL_PP(zv_pp) );
}
}

//================================================================================

PHP7中的定义返回值的宏 Zend/zend_API.h
define RETVAL_BOOL(b) ZVAL_BOOL(return_value, b)
define RETVAL_NULL() ZVAL_NULL(return_value)
define RETVAL_LONG(l) ZVAL_LONG(return_value, l)
define RETVAL_DOUBLE(d) ZVAL_DOUBLE(return_value, d)
define RETVAL_STR(s) ZVAL_STR(return_value, s)
define RETVAL_INTERNED_STR(s) ZVAL_INTERNED_STR(return_value, s)
define RETVAL_NEW_STR(s) ZVAL_NEW_STR(return_value, s)
define RETVAL_STR_COPY(s) ZVAL_STR_COPY(return_value, s)
define RETVAL_STRING(s) ZVAL_STRING(return_value, s)
define RETVAL_STRINGL(s, l) ZVAL_STRINGL(return_value, s, l)
define RETVAL_EMPTY_STRING() ZVAL_EMPTY_STRING(return_value)
define RETVAL_RES(r) ZVAL_RES(return_value, r)
define RETVAL_ARR(r) ZVAL_ARR(return_value, r)
define RETVAL_OBJ(r) ZVAL_OBJ(return_value, r)
define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
define RETVAL_FALSE ZVAL_FALSE(return_value)
define RETVAL_TRUE ZVAL_TRUE(return_value)


define RETURN_BOOL(b) { RETVAL_BOOL(b); return; }
define RETURN_NULL() { RETVAL_NULL(); return;}
define RETURN_LONG(l) { RETVAL_LONG(l); return; }
define RETURN_DOUBLE(d) { RETVAL_DOUBLE(d); return; }
define RETURN_STR(s) { RETVAL_STR(s); return; }
define RETURN_INTERNED_STR(s) { RETVAL_INTERNED_STR(s); return; }
define RETURN_NEW_STR(s) { RETVAL_NEW_STR(s); return; }
define RETURN_STR_COPY(s) { RETVAL_STR_COPY(s); return; }
define RETURN_STRING(s) { RETVAL_STRING(s); return; }
define RETURN_STRINGL(s, l) { RETVAL_STRINGL(s, l); return; }
define RETURN_EMPTY_STRING() { RETVAL_EMPTY_STRING(); return; }
define RETURN_RES(r) { RETVAL_RES(r); return; }
define RETURN_ARR(r) { RETVAL_ARR(r); return; }
define RETURN_OBJ(r) { RETVAL_OBJ(r); return; }
define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
define RETURN_FALSE { RETVAL_FALSE; return; }
define RETURN_TRUE { RETVAL_TRUE; return; }
array_init(return_value);//初始化return_value成数组,此操作完后就可以返回一个空的数组
object_init(return_value);//初始化return_value成Object,此操作完成后返回一个空的对像




//===============================================================================
grep "define ZEND_ACC" Zend/*.h
内核中提供了定义类以方法的修饰词 Zend/zend_compile.h声明定义

define ZEND_ACC_STATIC 0x01
define ZEND_ACC_ABSTRACT 0x02
define ZEND_ACC_FINAL 0x04
define ZEND_ACC_IMPLEMENTED_ABSTRACT 0x08
define ZEND_ACC_IMPLICIT_ABSTRACT_CLASS 0x10
define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS 0x20
define ZEND_ACC_INTERFACE 0x40
define ZEND_ACC_TRAIT 0x80
define ZEND_ACC_ANON_CLASS 0x100
define ZEND_ACC_ANON_BOUND 0x200

define ZEND_ACC_PUBLIC 0x100
define ZEND_ACC_PROTECTED 0x200
define ZEND_ACC_PRIVATE 0x400
define ZEND_ACC_PPP_MASK (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE)
define ZEND_ACC_CHANGED 0x800
define ZEND_ACC_IMPLICIT_PUBLIC 0x1000
define ZEND_ACC_CTOR 0x2000
define ZEND_ACC_DTOR 0x4000
define ZEND_ACC_CLONE 0x8000


//===============================================================================
1. grep ZEND_ACC Zend/*.h
内核中提供了定义类属性的宏 Zend/zend_API.h声明定义

ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment);
ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type);
ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type);
ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type);
ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type);
ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type);
ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type);
ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_len, int access_type);


更新类中的数据成员 Zend/zend_API.h声明定义

ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zval *value);
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value);
ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, size_t name_length);
ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value);
ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value);
ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, size_t name_length, double value);
ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_string *value);
ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value);
ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value, size_t value_length);

grep "zend_read_" ../../Zend/*.h
读取类中的数据成员 在Zend/zend_API.h声明定义

ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent, zval *rv);



//===============================================================================
2. grep "zend_declare_class_constant" Zend/*.h
创建类中的常量的方法在Zend/zend_API.h声明定义

ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value);
ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length);
ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value);
ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value);
ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value);
ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length);
ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value);

更新类中的常量数据成员 Zend/zend_API.h声明定义
ZEND_API int zend_update_class_constants(zend_class_entry *class_type);



//=================================================================================
3. grep "zend_update_static_" ../../Zend/*.h
更新类中的静态数据成员 在Zend/zend_API.

ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value);
ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length);
ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value);
ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value);
ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value);
ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value);
ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_length);


grep "zend_read_" ../../Zend/*.h
读取类中的数据成员 在Zend/zend_API.h声明定义

ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent);


```

- 请尊重本人劳动成功,可以随意转载但保留以下信息
- 作者:岁月经年
- 时间:2016年04月

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。