define() vs const 该如何选择?
使用 define(),除非考虑到可读性、类常量、或关注微优化
1、在 PHP 中是使用 define() 函数来定义常量,PHP 5.3.0 以后,PHP 中也能够使用 const 关键字来声明常量了,一个常量一旦被定义,就不能再改变或者取消定义
2、常量只能包含标量数据(boolean,integer,float 和 string)。可以定义 resource 常量,但应尽量避免,因为会造成不可预料的结果
3、可以简单的通过指定其名字来取得常量的值,与变量不同,不应该在常量前面加上 $ 符号。如果常量名是动态的,也可以用函数 constant() 来获取常量的值。用 get_defined_constants() 可以获得所有已定义的常量列表
Note: 常量和(全局)变量在不同的名字空间中。这意味着例如 TRUE 和 $TRUE 是不同的
常量和变量有如下不同
常量前面没有美元符号($);
常量只能用 define() 函数定义,而不能通过赋值语句;
常量可以不用理会变量的作用域而在任何地方定义和访问;
常量一旦定义就不能被重新定义或者取消定义;
常量的值只能是标量。
define vs const
1、define() 在执行期定义常量,使用 const 关键字定义常量必须处于最顶端的作用区域,因为用此方法是在编译时定义的,这就意味着不能在函数内,循环内以及 if 语句之内用 const 来定义常量,这样 const 就有轻微的速度优势, 但不值得考虑这个问题
2、define() 将常量放入全局作用域,虽然你可以在常量名中包含命名空间, 这意味着你不能使用 define() 定义类常量
3、define() 允许你在常量名和常量值中使用表达式,而 const 则都不允许,这使得 define() 更加灵活
示例
1、const不能使用条件表达式定义常量. 如果要定义一个全局常量,只能在表达式外面
if (...) {
const FOO = 'BAR'; // invalid
}
// but
if (...) {
define('FOO', 'BAR'); // valid
}
2、const 可以使用一个静态标量 (number, string or other constant like true, false, null, __FILE__), 反之define()没有限制.不过从 PHP 5.6 之后可以使用常量表达式
const BIT_5 = 1 << 5; // valid since PHP 5.6, invalid previously
define('BIT_5', 1 << 5); // always valid
3、const 使用一个普通的常量名称 反之define() 可以使用任意的常量表达式
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}
4、const总是大小写敏感的, 反之define() 允许你定义一个大小写不敏感的常量通过第三个参数
define('FOO', 'BAR', true);
echo FOO; // BAR
echo foo; // BAR
5、const simply reads nicer. It's a language construct instead of a function and also is consistent with how you define constants in classes,const defines a constant in the current namespace, while define() has to be passed the full namespace name:
namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = 'BAR';
define('A\B\C\FOO', 'BAR');
6、Since PHP 5.6 const constants can also be arrays, while define() does not support arrays yet. However arrays will be supported for both cases in PHP 7.
const FOO = [1, 2, 3]; // valid in PHP 5.6
define('FOO', [1, 2, 3]); // invalid in PHP 5.6, valid in PHP 7.0
As consts are language constructs and defined at compile time they are a bit faster than define().
It is well known that PHP define() are slow when using a large number of constants. People have even invented things like apc_load_constants() and hidef to get around this.
consts make the definition of constants approximately twice as fast (on development machines with XDebug turned on even more). Lookup time on the other hand does not change (as both constant types share the same lookup table)
Finally, note that const can also be used within a class or interface to define a class constant or interface constant. define cannot be used for this purpose:
class Foo {
const BAR = 2; // valid
}
// but
class Baz {
define('QUX', 2); // invalid
}
Summary
Unless you need any type of conditional or expressional definition, use consts instead of define()s - simply for the sake of readability!
<?php
// 来看看这两种方法如何处理 namespaces
namespace MiddleEarth\Creatures\Dwarves;
const GIMLI_ID = 1;
define('MiddleEarth\Creatures\Elves\LEGOLAS_ID', 2); echo(\MiddleEarth\Creatures\Dwarves\GIMLI_ID); // 1
echo(\MiddleEarth\Creatures\Elves\LEGOLAS_ID); // 2; 注意:我们使用了 define() // Now let's declare some bit-shifted constants representing ways to enter Mordor.
define('TRANSPORT_METHOD_SNEAKING', 1 << 0); // OK!
const TRANSPORT_METHOD_WALKING = 1 << 1; //Compile error! const can't use expressions as values // 接下来, 条件常量。
define('HOBBITS_FRODO_ID', 1); if($isGoingToMordor){
define('TRANSPORT_METHOD', TRANSPORT_METHOD_SNEAKING); // OK!
const PARTY_LEADER_ID = HOBBITS_FRODO_ID // 编译错误: const 不能用于 if 块中
} // 最后, 类常量
class OneRing{
const MELTING_POINT_DEGREES = 1000000; // OK!
define('SHOW_ELVISH_DEGREES', 200); // 编译错误: 在类内不能使用 define()
}
?>
无论你选择哪一种,请保持一致
看一下define在内核中如何实现的
/* {{{ 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;
}
}
/* }}} */
/* {{{ proto bool defined(string constant_name)
Check whether a constant exists */
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);
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}
/* }}} */
const
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
{
char *lowercase_name = NULL;
char *name;
int ret = SUCCESS;
ulong chash = 0; #if 0
printf("Registering constant for module %d\n", c->module_number);
#endif if (!(c->flags & CONST_CS)) {
/* keep in mind that c->name_len already contains the '\0' */
lowercase_name = estrndup(c->name, c->name_len-1);
zend_str_tolower(lowercase_name, c->name_len-1);
lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
name = lowercase_name;
chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
} else {
char *slash = strrchr(c->name, '\\');
if(slash) {
lowercase_name = estrndup(c->name, c->name_len-1);
zend_str_tolower(lowercase_name, slash-c->name);
lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
name = lowercase_name; chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
} else {
name = c->name;
}
}
if (chash == 0) {
chash = zend_hash_func(name, c->name_len);
} /* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
if ((c->name_len == sizeof("__COMPILER_HALT_OFFSET__")
&& !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1))
|| zend_hash_quick_add(EG(zend_constants), name, c->name_len, chash, (void *) c, sizeof(zend_constant), NULL)==FAILURE) { /* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */
if (c->name[0] == '\0' && c->name_len > sizeof("\0__COMPILER_HALT_OFFSET__")
&& memcmp(name, "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) {
name++;
}
zend_error(E_NOTICE,"Constant %s already defined", name);
str_free(c->name);
if (!(c->flags & CONST_PERSISTENT)) {
zval_dtor(&c->value);
}
ret = FAILURE;
}
if (lowercase_name && !IS_INTERNED(lowercase_name)) {
efree(lowercase_name);
}
return ret;
}
参考
define() vs const 该如何选择?的更多相关文章
- #define、const、typedef的区别
#define.const.typedef的区别 #define 并不是定义变量, 只是用来做文本替换 例如: #define PI 3.1415926 float angel; angel=30*P ...
- IOS 基础-define、const、extern、全局变量
这里介绍一下define.const.extern的用法.优劣以及要注意的地方. 1.define 宏define是定义一个变量,没有类型信息.define定义的常量在内存中有若干个拷贝. defin ...
- #define和const的简单区别
面试常问:宏#define和const有什么区别? 1.编译器处理方式 define宏是在预处理阶段展开 const常量是在编译阶段使用 2.类型和安全检查不同 define宏没有类型,不做安全检查, ...
- PHP中定义常量define与const
我们通常把不经常变的值定义成常量,常量一般用全部大写来表示,前面不加美元符号,也可减少团队开发的出错.那么define和const有什么区别呢? 1.const是一个语言结构:而define是一个函数 ...
- 宏定义define和const的区别
define和const都可以用来定义常量,define的格式为:#define 标识符 字符串,const在定义常量前面,const类型定以后不能被修改,区别主要有如下几点: 1.编译器处理方式不同 ...
- iOS学习——#define、const、typedef的区别
在iOS开发中经常遇到一些字段和类型的定义,例如配置生产和测试不同环境的参数等,这时候经常用到#define.const以及typedef.那么它们之间有什么区别呢?我们接下来一个一个具体了解下. 一 ...
- PHP中的Define和Const区别
我们经常把不经常变的值定义成常量,常量一般用全部大写来表示,前面不加美元符号,那么define和const有什么区别呢? 常量是一个简单的标识符.在脚本执行期间该值不能改变(除了所谓的魔术常量,他们其 ...
- c++中typedef、define、const、inline之间的区别
1.typedef和#define的区别 typedef int* pInt; , b = ; const pInt p1 = &a; //p1是常量指针 pInt const p2 = &a ...
- 在php中define和const定义常量的区别
define和const都可以用来定义常量,但是const定义常量的时候大小写敏感,而define可以通过设置第三个参数为true的时候来取消大小写敏感! 如图: 引用地址:点这里
随机推荐
- RobotFramework自动化4-批量操作案例
前言 有时候一个页面上有多个对象需要操作,如果一个个去定位的话,比较繁琐,这时候就可以定位一组对象.Selenium2library提供了Get Webelements 关键字,用于定位一组元素 以百 ...
- ubuntu下如何查看自己的外网IP
1.1 安装使用curl命令实现 sudo apt-get install curl1.2 输入命令 curl ifconfig.me
- 解决hue/hiveserver2对于hive date类型显示为NULL的问题
用户报在Hue中执行一条sql:select admission_date, discharge_date,birth_date from hm_004_20170309141149.inpatien ...
- Lombok的安装及入门
lombok 的官方网址:http://projectlombok.org/ lombok 其实到这里我就介绍完了,开个玩笑,其实官网上有 lombok 三分四十九秒的视频讲解,里面讲的也很清楚了,而 ...
- 内存及字符串操作篇strlen strchar strcmp strcoll strcpy strdup strstr strtok strspn strrchr bcmp bcopy bzero index memccpy memset
bcmp(比较内存内容) 相关函数 bcmp,strcasecmp,strcmp,strcoll,strncmp,strncasecmp 表头文件 #include<string.h> 定 ...
- vijos p1729 Knights
描述 在一个N*N的正方形棋盘上,放置了一些骑士.我们将棋盘的行用1开始的N个自然数标记,将列用'A'开始的N个大写英文字母标记.举个例子来说,一个标准的8*8的国际象棋棋盘的行标记为1..8,列标记 ...
- 3D有向包围盒与球体碰撞的算法
之前发的小游戏滚蛋躲方块中,用它来判断球体与立方体是否发生了碰撞. http://www.cnblogs.com/WhyEngine/p/3350012.html 现在发布下该算法: 有向包围盒OBB ...
- 锐浪报表 导出 PDF ANSI码 乱码 问题解决
锐浪 报表 导出PDF时如果 ANSI 码 打勾了会乱码,能将这个选项默认不打勾吗 //在报表导出事件脚本里写脚本,可实现导出控制Sender.AsE2PDFOption.AnsiTextMode=0 ...
- 【记录】cygwin下折腾个人配置环境
(本文由hcbbt发布,转载请注明出处,blog.csdn[dot]net/hcbbT) cygwin是windows下的linux的模拟环境,不仅可以执行linux的各种命令,可以在cyg ...
- ECMAScript5之Object学习笔记(三)
第三部分继续... Object.getOwnPropertyDescriptor(obj, prop) 获取一个对象的属性描述符 根据"Own"这个词我们可以猜到,prop只能是 ...