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

本文详细指导如何使用C语言为PHP定制MVC结构,涉及配置修改、C文件内容编写、类定义与方法实现,以及编译安装过程。重点讲解了路由解析、加载文件及类操作的步骤和相关技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

```

场景:想要用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月

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

相关文章

相关视频

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值