0

0

【php原理】狂言php常量

php中文网

php中文网

发布时间:2016-06-13 12:00:46

|

1215人浏览过

|

来源于php中文网

原创

【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;	}}/* }}} */

 

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

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

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Word 字间距调整方法汇总
Word 字间距调整方法汇总

本专题整合了Word字间距调整方法,阅读下面的文章了解更详细操作。

2

2025.12.24

任务管理器教程
任务管理器教程

本专题整合了任务管理器相关教程,阅读下面的文章了解更多详细操作。

2

2025.12.24

AppleID格式
AppleID格式

本专题整合了AppleID相关内容,阅读专题下面的文章了解更多详细教程。

0

2025.12.24

csgo视频观看入口合集
csgo视频观看入口合集

本专题整合了csgo观看入口合集,阅读下面的文章了知道更多入口地址。

29

2025.12.24

yandex外贸入口合集
yandex外贸入口合集

本专题汇总了yandex外贸入口地址,阅读下面的文章了解更多内容。

58

2025.12.24

添加脚注通用方法
添加脚注通用方法

本专题整合了添加脚注方法合集,阅读专题下面的文章了解更多内容。

1

2025.12.24

重启电脑教程汇总
重启电脑教程汇总

本专题整合了重启电脑操作教程,阅读下面的文章了解更多详细教程。

3

2025.12.24

纸张尺寸汇总
纸张尺寸汇总

本专题整合了纸张尺寸相关内容,阅读专题下面的文章了解更多内容。

5

2025.12.24

Java Spring Boot 微服务实战
Java Spring Boot 微服务实战

本专题深入讲解 Java Spring Boot 在微服务架构中的应用,内容涵盖服务注册与发现、REST API开发、配置中心、负载均衡、熔断与限流、日志与监控。通过实际项目案例(如电商订单系统),帮助开发者掌握 从单体应用迁移到高可用微服务系统的完整流程与实战能力。

1

2025.12.24

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
zend框架2视频教程
zend框架2视频教程

共79课时 | 13.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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