使用 define(),除非考虑到可读性、类常量、或关注微优化

1、在 PHP 中是使用 define() 函数来定义常量,PHP 5.3.0 以后,PHP 中也能够使用 const 关键字来声明常量了,一个常量一旦被定义,就不能再改变或者取消定义

2、常量只能包含标量数据(booleanintegerfloatstring)。可以定义 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 该如何选择?的更多相关文章

  1. #define、const、typedef的区别

    #define.const.typedef的区别 #define 并不是定义变量, 只是用来做文本替换 例如: #define PI 3.1415926 float angel; angel=30*P ...

  2. IOS 基础-define、const、extern、全局变量

    这里介绍一下define.const.extern的用法.优劣以及要注意的地方. 1.define 宏define是定义一个变量,没有类型信息.define定义的常量在内存中有若干个拷贝. defin ...

  3. #define和const的简单区别

    面试常问:宏#define和const有什么区别? 1.编译器处理方式 define宏是在预处理阶段展开 const常量是在编译阶段使用 2.类型和安全检查不同 define宏没有类型,不做安全检查, ...

  4. PHP中定义常量define与const

    我们通常把不经常变的值定义成常量,常量一般用全部大写来表示,前面不加美元符号,也可减少团队开发的出错.那么define和const有什么区别呢? 1.const是一个语言结构:而define是一个函数 ...

  5. 宏定义define和const的区别

    define和const都可以用来定义常量,define的格式为:#define 标识符 字符串,const在定义常量前面,const类型定以后不能被修改,区别主要有如下几点: 1.编译器处理方式不同 ...

  6. iOS学习——#define、const、typedef的区别

    在iOS开发中经常遇到一些字段和类型的定义,例如配置生产和测试不同环境的参数等,这时候经常用到#define.const以及typedef.那么它们之间有什么区别呢?我们接下来一个一个具体了解下. 一 ...

  7. PHP中的Define和Const区别

    我们经常把不经常变的值定义成常量,常量一般用全部大写来表示,前面不加美元符号,那么define和const有什么区别呢? 常量是一个简单的标识符.在脚本执行期间该值不能改变(除了所谓的魔术常量,他们其 ...

  8. c++中typedef、define、const、inline之间的区别

    1.typedef和#define的区别 typedef int* pInt; , b = ; const pInt p1 = &a; //p1是常量指针 pInt const p2 = &a ...

  9. 在php中define和const定义常量的区别

    define和const都可以用来定义常量,但是const定义常量的时候大小写敏感,而define可以通过设置第三个参数为true的时候来取消大小写敏感! 如图: 引用地址:点这里

随机推荐

  1. python测试开发django-10.django连接mysql

    前言 Django 对各种数据库提供了很好的支持,包括:PostgreSQL.MySQL.SQLite.Oracle.本篇以mysql为例简单介绍django连接mysql进行数据操作 Django连 ...

  2. 使用开源库 SDWebImage 异步下载缓存图片(持续更新)

    source  https://github.com/rs/SDWebImage APIdoc  http://hackemist.com/SDWebImage/doc Asynchronous im ...

  3. Solution Explorer 和 Source Control Explorer 的 View History 异同

    如果查看别人对代码的修改,你可能会非常烦恼与在 Solution Explorer 中看历史版本看不全,如下: 实际上,你想看到的是对于整个解决方案,全部的历史版本,那应该跑去 Source Cont ...

  4. Configuring HDFS High Availability

    Configuring HDFS High Availability 原文请訪问 http://blog.csdn.net/ashic/article/details/47024617,突袭新闻小灵儿 ...

  5. iOS:制作一个简易的计算器

    初步接触视图,制作了一个简易的计算器,基本上简单的计算是没有问题的,不是很完美,可能还有一些bug,再接再厉. // // ViewController.m // 计算器 // // Created ...

  6. quickcocos2dx framework环境变 fatal error C1083: 无法打开源文件:“.Box2D/Dynamics/b2World.h”: No such file or d

      : fatal error C1083: 无法打开源文件:".Box2D/Dynamics/b2World.h": No such file or directory 解决方法 ...

  7. 关于PHP写的投票网站之刷票风云

    最近学校导航站找我让我给他们做一个投票系统的网站,我一口答应了,他们只是要求不准刷票情况出现,我也一口答应了..我答应的太干脆了. 然后我便开始做这个网站,网站做出来没花太多时间,并且我是用IP来判断 ...

  8. 为Ubuntu 安装Transmission 2.90

    Transmission 是 Ubuntu 的默认 BitTorrent 客户端,近期发布了最新的 Transmission 2.90 版本,目前已经可通过 PPA 为 Ubuntu 15.10.Ub ...

  9. [HTML5] Avoiding CSS Conflicts via Shadow DOM CSS encapsulation

    Shadow DOM is part of the web components specification. It allows us to ship self contained componen ...

  10. C#.NET常见问题(FAQ)-使用SharpDevelop开发 如何切换设计视图和代码视图

    仅在MainForm.cs跟MainForm.Designer.cs文件页面上,底部有可以切换源代码跟设计的按钮(别的地方都木有)   点击就切换过来了     更多教学视频和资料下载,欢迎关注以下信 ...