php类 静态变量赋值 static $name="abc"
2015-04-16 11:54
197 查看
<?php class test { static $name="abc"; } echo test::$name;
1.巴斯科范式
class_statement: variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';' ; member_modifier: T_PUBLIC { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; } | T_PROTECTED { Z_LVAL($$.u.constant) = ZEND_ACC_PROTECTED; } | T_PRIVATE { Z_LVAL($$.u.constant) = ZEND_ACC_PRIVATE; } | T_STATIC { Z_LVAL($$.u.constant) = ZEND_ACC_STATIC; } | T_ABSTRACT { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; } | T_FINAL { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; } ; class_variable_declaration: class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); } | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); } | T_VARIABLE { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); } | T_VARIABLE '=' static_scalar { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); } ; variable: T_STRING T_PAAMAYIM_NEKUDOTAYIM base_variable { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); } ; base_variable: T_VARIABLE { fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); } ;
理解版
class_statement: variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';' ; member_modifier: T_PUBLIC { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; } | T_PROTECTED { Z_LVAL($$.u.constant) = ZEND_ACC_PROTECTED; } | T_PRIVATE { Z_LVAL($$.u.constant) = ZEND_ACC_PRIVATE; } | T_STATIC { Z_LVAL($$.u.constant) = ZEND_ACC_STATIC; } | T_ABSTRACT { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; } | T_FINAL { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; } ; class_variable_declaration: class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); } | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); } | T_VARIABLE { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); } | T_VARIABLE '=' static_scalar { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); } ; variable: T_STRING T_PAAMAYIM_NEKUDOTAYIM T_VARIABLE { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); } ;
2.对于 static $name="abc"
组织propert_info结构体,将其存于为类中的property_info 这个HashTable中,
注意: value 这个值是存在类中的property_table中,其中key 为property_info中的offset
void zend_do_declare_property(const znode *var_name, const znode *value, zend_uint access_type TSRMLS_DC) /* {{{ */ { zval *property; ALLOC_ZVAL(property); if (value) { *property = value->u.constant; } else { INIT_PZVAL(property); Z_TYPE_P(property) = IS_NULL; } zend_declare_property_ex(CG(active_class_entry), zend_new_interned_string(Z_STRVAL(var_name->u.constant), Z_STRLEN(var_name->u.constant) + 1, 0 TSRMLS_CC), Z_STRLEN(var_name->u.constant), property, access_type, comment, comment_len TSRMLS_CC); }
ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, const char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */ { zend_property_info property_info, *property_info_ptr; const char *interned_name; ulong h = zend_get_hash_value(name, name_length+1); if (access_type & ZEND_ACC_STATIC) { //如果是静态成员变量,就使用relloc分配需要的内存,size(zval*)*ce->default_static_member_count是总共的内存 property_info.offset = ce->default_static_members_count++; ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS); ce->default_static_members_table[property_info.offset] = property; if (ce->type == ZEND_USER_CLASS) { ce->static_members_table = ce->default_static_members_table; } } else { property_info.offset = ce->default_properties_count++; ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS); ce->default_properties_table[property_info.offset] = property; } interned_name = zend_new_interned_string(property_info.name, property_info.name_length+1, 0 TSRMLS_CC); if (interned_name != property_info.name) { if (ce->type == ZEND_USER_CLASS) { efree((char*)property_info.name); } else { free((char*)property_info.name); } property_info.name = interned_name; } property_info.flags = access_type; property_info.h = (access_type & ZEND_ACC_PUBLIC) ? h : zend_get_hash_value(property_info.name, property_info.name_length+1); property_info.ce = ce; zend_hash_quick_update(&ce->properties_info, name, name_length+1, h, &property_info, sizeof(zend_property_info), NULL); return SUCCESS; }
void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */ { znode class_node; zend_llist *fetch_list_ptr; zend_llist_element *le; zend_op *opline_ptr; zend_op opline; zend_do_fetch_class(&class_node, class_name TSRMLS_CC); if (result->op_type == IS_CV) { init_op(&opline TSRMLS_CC); opline.opcode = ZEND_FETCH_W; opline.result_type = IS_VAR; opline.result.var = get_temporary_variable(CG(active_op_array)); opline.op1_type = IS_CONST; //opline->op1为 成员变量的值,result->u.op.var为fetch_simple_variable所获得的值 LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[result->u.op.var].name), CG(active_op_array)->vars[result->u.op.var].name_len, 0); CALCULATE_LITERAL_HASH(opline.op1.constant); GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant); //class_node.op_type此时为IS_VAR if (class_node.op_type == IS_CONST) { opline.op2_type = IS_CONST; opline.op2.constant = zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC); } else { SET_NODE(opline.op2, &class_node); } GET_NODE(result,opline.result); opline.extended_value |= ZEND_FETCH_STATIC_MEMBER; opline_ptr = &opline; zend_llist_add_element(fetch_list_ptr, &opline); }
zend_do_fetch_class 函数的运行
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *class_name = opline->op2.zv; if (CACHED_PTR(opline->op2.literal->cache_slot)) { EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot); } else { EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC); CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry); //记住 这里被缓存住了 } }
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *varname; zval **retval; SAVE_OPLINE(); varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_class_entry *ce; ce = CACHED_PTR(opline->op2.literal->cache_slot); retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); }
找到成员变量
ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, zend_bool silent, const zend_literal *key TSRMLS_DC) /* {{{ */ { zend_property_info *property_info; ulong hash_value; hash_value = zend_hash_func(property_name, property_name_len+1); //即使这里的类是子类,子类的ce->properties_info的数据复制于父类的properties_info这个hash table if (UNEXPECTED(zend_hash_quick_find(&ce->properties_info, property_name, property_name_len+1, hash_value, (void **) &property_info)==FAILURE)) { if (!silent) { zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name); } return NULL; } if (UNEXPECTED(!zend_verify_property_access(property_info, ce TSRMLS_CC))) { if (!silent) { zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name); } return NULL; } if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) { if (!silent) { zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name); } return NULL; } if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL) || UNEXPECTED(CE_STATIC_MEMBERS(ce)[property_info->offset] == NULL)) { if (!silent) { zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name); } return NULL; } return &CE_STATIC_MEMBERS(ce)[property_info->offset]; }
相关文章推荐
- @Value(value="${***.***}")配置文件赋值给static静态变量
- QString 赋值为 "" 才能查询 name 为空的记录。
- static 静态变量和静态函数的使用探究 类::functionname 与 初始化一个对象的区别
- "name":function(){}和function name(){}这样的写法有什么区别?
- document.getElementById("")和document.getElementsByName()和document.getElementsByTagName()有什么区别
- 小甲鱼第51讲:《__name__="__main__"、搜索路径和包》课后练习题
- Struts2中关于"There is no Action mapped for namespace / and action name"的总结
- uses-permission android:name="android.permission.INSTALL_PACKAGES 报错
- python-字典增删改查、遍历、方法、a,b=["dd","gg"]赋值方式
- Invalid name: "@types/node"
- meta name="viewport"
- 移动web页面中<meta name="viewport" 等等>
- ssh框架整合的一个教偏的用法<sql-query callable="true" name="myDirInfo">
- final、static、static final修饰的字段赋值的区别
- Hadoop 解除 "Name node is in safe mode"
- struts标签格式化时间<s:date name="neowaveBloodPressure.monitorTime" format="yyyy-MM-dd HH:mm:ss" />
- spring3 页面form标签 报错 Neither BindingResult nor plain target object for bean name "company"
- Spring Boot使用Value注解给静态变量赋值的方法
- struts的<package name="login" namespace="/system" extends="struts-default">是什么意思?
- An invalid form control with name='file[]' is not focusable.间接点击form表单的<input type="file">出现的问题