存储结构
常量存储在哈希表EG(zend_constants)中。
常量的结构定义为:
|
|
value是常量的值,是一个zval。name是常量名。module_number是模块被加载时,PHP内核在MINIT和RINIT方法的原型里默认传递的一个值,作为模块清理时的线索,在注册常量的接口里直接传递即可。
flags是常量的标识或标识组合:
- CONST_CS
- CONST_PERSISTENT
- CONST_CT_SUBST
CONST_CS表示常量名对大小写敏感,对应PHP函数define()的第三个参数,TRUE、FALSE、NULL这些常量名对大小写是不敏感的。CONST_PERSISTENT表示常量在请求结束后被保存,只在PHP进程结束时才销毁,一般在MINIT中定义的常量应该指定此参数,RINIT中定义的不指定。CONST_CT_SUBST表示在编译时可替换,TRUE、FALSE、NULL、ZEND_THREAD_SAFE、ZEND_DEBUG_BUILD属于此类。
常量的声明
常量的声明方法有两种,简单的使用宏函数族REGISTER_*_CONSTANT():
REGISTER_NULL_CONSTANT(name, flags) REGISTER_BOOL_CONSTANT(name, bval, flags) REGISTER_LONG_CONSTANT(name, lval, flags) REGISTER_DOUBLE_CONSTANT(name, dval, flags) REGISTER_STRING_CONSTANT(name, str, flags) REGISTER_STRINGL_CONSTANT(name, str, len, flags)
由于不需指定常量名长度,所以name参数应直接使用字符串,而不是char*。
如需使用变量作为name参数,使用zend_register_*_constant()函数族,并指定变量名长度(sizeof(name))。上面的宏函数其实是对这族函数的封装。
void zend_register_long_constant(char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC) void zend_register_double_constant(char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC) void zend_register_bool_constant(const char *name, uint name_len, zend_bool bval, int flags, int module_number TSRMLS_DC) void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC) void zend_register_stringl_constant(char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC)
除此之外,还有REGISTER_MAIN_*_CONSTANT和REGISTER_NS_*_CONSTANT两组宏函数。前者用于定义像E_ERROR这样的PHP标准常量,后者定义有命令空间的常量。
define()和const
- define()是函数,在运行时定义常量
- 不能定义类常量
- 可以在条件语句中使用
- 可以指定常量是否对大小写敏感
- 可以用表达式作为常量值
- 只定义全局常量,不支持命名空间
- const是语句,在编译时定义常量
- 可以定义类常量
- 不能在条件语句中使用
- 定义的常量对大小写敏感
- 不支持表达式作为常量值
- 若脚本定义了命名空间,声明的常量属于该命名空间
魔术常量
__LINE__
__FILE__
__DIR__
__FUNCTION__
__CLASS__
__METHOD__
__NAMESPACE__
魔术常量是在编译时(具体地说是词法分析时,见Zend/zend_language_scanner.l)被替换,确切地说,这些不是真正意义上的常量,只是个模板占位符。