常量php
什麼是常量.ide
常量就是不變的量.
先看看常量的結構函數
- typedef struct _zend_constant {
- zval value;//zval類型
- int flags;//標示 是否大小寫敏感
- char *name;//常量名稱
- uint name_len;//長度
- int module_number;//標示是用戶定義的常量 不是系統常量
- } zend_constant;
PHP定義常量以下fetch
- <?php
- define('TEST',1);
很簡單 .定義了一個常量ui
那在內核裏都作了什麼?lua
打開 zend/zend_builtin_functions.c PHP的內置函數都在這裏spa
找到 ZEND_FUNCTION(define)scala
代碼以下orm
- 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;//這個是常量的struct
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b", &name, &name_len, &val, &non_cs) == FAILURE) {
- return;
- }
- if(non_cs) {//define第三個參數的做用,大小寫是否敏感 若是爲真 大小寫不敏感
- case_sensitive = 0;
- }
- //PHP5.3新特性:類常量,暫不作介紹
- 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);//徹底拷貝 由於val是zval類型,除了value還有其餘屬性,用這個宏徹底拷貝過來
- if (val_free) {
- zval_ptr_dtor(&val_free);
- }
- c.flags = case_sensitive; //大小寫敏感?
- c.name = zend_strndup(name, name_len); //拷貝name
- 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;
- }
- }
既然說了define 那就確定要說說defined了
defined用來檢測 常量是否已經定義
這個其實很簡單 代碼以下遞歸
- ZEND_FUNCTION(defined)
- {
- char *name;
- int name_len;
- zval c;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
- return;
- }
- if (zend_get_constant_ex(name, name_len, &c, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC)) {//找到了
- zval_dtor(&c); //釋放zval.value的內存
- RETURN_TRUE;
- } else {//沒找到
- RETURN_FALSE;
- }
- }
主要的工做在 zend_get_constant_ex這個函數裏
- ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC)
- {
- zend_constant *c; //常量類型
- int retval = 1;
- char *colon;
- zend_class_entry *ce = NULL;
- char *class_name;
- zval **ret_constant;
- /* Skip leading \\ */
- if (name[0] == '\\') {
- name += 1;
- name_len -= 1;
- }
- if ((colon = zend_memrchr(name, ':', name_len)) &&
- colon > name && (*(colon - 1) == ':')) { //類常量 暫不作介紹
- int class_name_len = colon - name - 1;
- int const_name_len = name_len - class_name_len - 2;
- char *constant_name = colon + 1;
- char *lcname;
- class_name = estrndup(name, class_name_len);
- lcname = zend_str_tolower_dup(class_name, class_name_len);
- if (!scope) {
- if (EG(in_execution)) {
- scope = EG(scope);
- } else {
- scope = CG(active_class_entry);
- }
- }
- if (class_name_len == sizeof("self")-1 &&
- !memcmp(lcname, "self", sizeof("self")-1)) {
- if (scope) {
- ce = scope;
- } else {
- zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
- retval = 0;
- }
- efree(lcname);
- } else if (class_name_len == sizeof("parent")-1 &&
- !memcmp(lcname, "parent", sizeof("parent")-1)) {
- if (!scope) {
- zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
- } else if (!scope->parent) {
- zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
- } else {
- ce = scope->parent;
- }
- efree(lcname);
- } else if (class_name_len == sizeof("static")-1 &&
- !memcmp(lcname, "static", sizeof("static")-1)) {
- if (EG(called_scope)) {
- ce = EG(called_scope);
- } else {
- zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
- }
- efree(lcname);
- } else {
- efree(lcname);
- ce = zend_fetch_class(class_name, class_name_len, flags TSRMLS_CC);
- }
- if (retval && ce) {
- if (zend_hash_find(&ce->constants_table, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
- retval = 0;
- if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
- zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name, constant_name);
- }
- }
- } else if (!ce) {
- retval = 0;
- }
- efree(class_name);
- goto finish;
- }
- //普一般量 colon爲反斜線以前的字符串
- if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) {
- /* compound constant name */
- int prefix_len = colon - name;
- int const_name_len = name_len - prefix_len - 1;
- char *constant_name = colon + 1;
- char *lcname;
- int found_const = 0;
- lcname = zend_str_tolower_dup(name, prefix_len);
- /* Check for namespace constant */
- /* Concatenate lowercase namespace name and constant name */
- lcname = erealloc(lcname, prefix_len + 1 + const_name_len + 1);
- lcname[prefix_len] = '\\';
- memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
- //查找常量
- if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
- found_const = 1;//找到了
- } else {//沒找到
- //轉換爲小寫從新查找
- zend_str_tolower(lcname + prefix_len + 1, const_name_len);
- if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {//找到了
- if ((c->flags & CONST_CS) == 0) {
- found_const = 1;
- }
- }
- }
- efree(lcname);
- if(found_const) {
- *result = c->value;
- zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC);
- zval_copy_ctor(result);
- Z_SET_REFCOUNT_P(result, 1);
- Z_UNSET_ISREF_P(result);
- return 1;
- }
- /* name requires runtime resolution, need to check non-namespaced name */
- if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) {
- name = constant_name;
- name_len = const_name_len;
- return zend_get_constant(name, name_len, result TSRMLS_CC);
- }
- retval = 0;
- finish:
- if (retval) {
- zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
- *result = **ret_constant;
- zval_copy_ctor(result);
- INIT_PZVAL(result);
- }
- return retval;
- }
- return zend_get_constant(name, name_len, result TSRMLS_CC);
- }
define就是將建立的常量 放在EG(zend_constants)裏
defined就是在EG(zend_constants)去遞歸查找