define() vs const 该如何选择?
使用 define(),除非考慮到可讀性、類(lèi)常量、或關(guān)注微優(yōu)化
1、在 PHP 中是使用 define() 函數(shù)來(lái)定義常量,PHP 5.3.0 以后,PHP 中也能夠使用 const 關(guān)鍵字來(lái)聲明常量了,一個(gè)常量一旦被定義,就不能再改變或者取消定義
2、常量只能包含標(biāo)量數(shù)據(jù)(boolean,integer,float 和 string)。可以定義 resource 常量,但應(yīng)盡量避免,因?yàn)闀?huì)造成不可預(yù)料的結(jié)果
3、可以簡(jiǎn)單的通過(guò)指定其名字來(lái)取得常量的值,與變量不同,不應(yīng)該在常量前面加上 $ 符號(hào)。如果常量名是動(dòng)態(tài)的,也可以用函數(shù) constant() 來(lái)獲取常量的值。用 get_defined_constants() 可以獲得所有已定義的常量列表
Note: 常量和(全局)變量在不同的名字空間中。這意味著例如 TRUE 和 $TRUE 是不同的
?
常量和變量有如下不同
?define vs const
1、define() 在執(zhí)行期定義常量,使用 const 關(guān)鍵字定義常量必須處于最頂端的作用區(qū)域,因?yàn)橛么朔椒ㄊ窃诰幾g時(shí)定義的,這就意味著不能在函數(shù)內(nèi),循環(huán)內(nèi)以及 if 語(yǔ)句之內(nèi)用 const 來(lái)定義常量,這樣 const 就有輕微的速度優(yōu)勢(shì), 但不值得考慮這個(gè)問(wèn)題
2、define() 將常量放入全局作用域,雖然你可以在常量名中包含命名空間, 這意味著你不能使用 define() 定義類(lèi)常量
3、define() 允許你在常量名和常量值中使用表達(dá)式,而 const 則都不允許,這使得 define() 更加靈活
示例
1、const不能使用條件表達(dá)式定義常量. 如果要定義一個(gè)全局常量,只能在表達(dá)式外面
if (...) {const FOO = 'BAR'; // invalid } // but if (...) {define('FOO', 'BAR'); // valid }2、const 可以使用一個(gè)靜態(tài)標(biāo)量 (number, string or other constant like true, false, null, __FILE__), 反之define()沒(méi)有限制.不過(guò)從 PHP 5.6 之后可以使用常量表達(dá)式
const BIT_5 = 1 << 5; // valid since PHP 5.6, invalid previously define('BIT_5', 1 << 5); // always valid?3、const 使用一個(gè)普通的常量名稱(chēng) 反之define() 可以使用任意的常量表達(dá)式
for ($i = 0; $i < 32; ++$i) {define('BIT_' . $i, 1 << $i); }?4、const總是大小寫(xiě)敏感的, 反之define() 允許你定義一個(gè)大小寫(xiě)不敏感的常量通過(guò)第三個(gè)參數(shù)
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 // 來(lái)看看這兩種方法如何處理 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// 接下來(lái), 條件常量。 define('HOBBITS_FRODO_ID', 1);if($isGoingToMordor){define('TRANSPORT_METHOD', TRANSPORT_METHOD_SNEAKING); // OK!const PARTY_LEADER_ID = HOBBITS_FRODO_ID // 編譯錯(cuò)誤: const 不能用于 if 塊中 }// 最后, 類(lèi)常量 class OneRing{const MELTING_POINT_DEGREES = 1000000; // OK!define('SHOW_ELVISH_DEGREES', 200); // 編譯錯(cuò)誤: 在類(lèi)內(nèi)不能使用 define() } ?>?無(wú)論你選擇哪一種,請(qǐng)保持一致
看一下define在內(nèi)核中如何實(shí)現(xiàn)的
/* {{{ 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 手冊(cè):常量
- Stack Overflow: define() vs. 變量
- 測(cè)試地址
轉(zhuǎn)載于:https://www.cnblogs.com/chenpingzhao/p/4811957.html
總結(jié)
以上是生活随笔為你收集整理的define() vs const 该如何选择?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: How draw a stem -and
- 下一篇: H5学习之旅-H5的样式(5)