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 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; // BAR5、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.0As 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 0printf("Registering constant for module %d\n", c->module_number); #endifif (!(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; }?
參考
- Stack Overflow: define() vs. const
- PHP 手冊:常量
- Stack Overflow: define() vs. 變量
- 測試地址
轉載于:https://www.cnblogs.com/chenpingzhao/p/4811957.html
總結
以上是生活随笔為你收集整理的define() vs const 该如何选择?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: How draw a stem -and
- 下一篇: H5学习之旅-H5的样式(5)