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

php中文网
发布: 2016-06-23 13:09:30
原创
1436人浏览过

```
场景:想要用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速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号