您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

【php原理】狂言php常量

2025/1/9 17:23:09发布29次查看
【php原理】大话php常量
我们先看一个php常量的定义方法
define('price', 30);
之前,我一直把define和c中的宏定义理解一致,因此在使用的时候也只是将其当成简单地字符替换。后来研究了php内核以后,发现php中的常量和宏定义完全不是一回事。
在php脚本运行的过程中,zend引擎会维护一个常量列表,对于普通用户来说,可以对这个常量列表进行crud操作,api分别为
define():定义一个常量
defined(): 判断一个常量是否存在
constant(): 得到一个常量的值
我们来看下php内核中常量的定义
typedef struct _zend_constant{ zval value; int flags; char *name; uint name_len; int module_number;} _zend_constant;
其中value为普通的变量结构zval,在此基础上,常量还定义了标记,常量名和模块号三个属性。
1. 标记(flags)
首先看常量的标记属性flag,目前可供选择的几个可能值分别为
用户态(可通过define方法的第三个参数赋值):
        1: case sensitive
        0: case insensitive
内核态:
        const_persistant: persistent
        const_ct_subst: allow compile-time substitution
用户定义的常量的标记默认为case sensitive, 也可通过define函数的第三个参数进行修改。对于内核态标记,const_persistant代表这个常量在内存申请的时候需要持久化。
上图是php脚本运行的的生命周期,我们知道多个request共享一次minit和mshutdown过程,而每个request有自己的rinit和rshutdown过程,因此在minit中初始化的变量会常驻内存当中。这样被标记为const_persistant的常量只会在mshutdown中才会被析构掉。这也就不难理解,在内核c代码中,一些字符串和数字作为代码的一部分也被定义为php内核中的常量,它们通常就会被标记为const_persistent常量。
而const_ct_subst目前在内核里只有5个(true, false, null, zend_thread_safe, zend_debug_build),
2.模块号(module_number)
模块号同样分为用户态和内核态,确切的说,模块号就是用来做此区分的。用户定义的常量均为php_user_constant, 除此以外,还有一些php内置的标准常量,例如e_all, e_warning等。在zend引擎启动以后,zend会进行标准常量的注册工作(zend_register_standard_constants()),一般来说,这些标准常量都被标记为持久化常量,即const_persistent
3. define()函数
define是php的内置接口,用户会通过define来定义常量,其实该方法过程如下
4. 魔术常量
php中还提供了一种魔术常量,他们的值是随着外部环境的变化而变化的,例如
__line__ 当前文件的行号
__file__ 文件的完整路径
这些魔术常量不是真正的常量(_zend_constants),php内核在此法解析的时候就会将其替换掉。
最后附上define的源码(在zend/zend_builtin_functions.c中):
/* {{{ proto bool define(string constant_name, mixed value, boolean case_insensitive=false) define a new constant */zend_function(define){ char *name; int name_len; zval *val; zval *val_free = null; zend_bool non_cs = 0; int case_sensitive = const_cs; zend_constant c; if (zend_parse_parameters(zend_num_args() tsrmls_cc, sz|b, &name, &name_len, &val, &non_cs) == failure) { return; } if(non_cs) { case_sensitive = 0; } /* class constant, check if there is name and make sure class is valid & exists */ if (zend_memnstr(name, ::, sizeof(::) - 1, name + name_len)) { zend_error(e_warning, class constants cannot be defined or redefined); return_false; }repeat: switch (z_type_p(val)) { case is_long: case is_double: case is_string: case is_bool: case is_resource: case is_null: break; case is_object: if (!val_free) { if (z_obj_ht_p(val)->get) { val_free = val = z_obj_ht_p(val)->get(val tsrmls_cc); goto repeat; } else if (z_obj_ht_p(val)->cast_object) { alloc_init_zval(val_free); if (z_obj_ht_p(val)->cast_object(val, val_free, is_string tsrmls_cc) == success) { val = val_free; break; } } } /* no break */ default: zend_error(e_warning,constants may only evaluate to scalar values); if (val_free) { zval_ptr_dtor(&val_free); } return_false; } c.value = *val; zval_copy_ctor(&c.value); if (val_free) { zval_ptr_dtor(&val_free); } c.flags = case_sensitive; /* non persistent */ c.name = is_interned(name) ? name : zend_strndup(name, name_len); if(c.name == null) { return_false; } c.name_len = name_len+1; c.module_number = php_user_constant; if (zend_register_constant(&c tsrmls_cc) == success) { return_true; } else { return_false; }}/* }}} */
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product