程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> define常量

define常量

編輯:關於PHP編程

看手冊說define定義的常量只允許:

僅允許標量和 null。標量的類型是 integer, float,string 或者 boolean。 也能夠定義常量值的類型為 resource ,但並不推薦這麼做,可能會導致未知狀況的發生。

今天閱讀php源碼,發現define的第二個參數其實也可以是一個對象。

先貼一段示例:

  'bar' = ('foo',  foo;
// 輸出bar

接著來看看php中的define究竟是如何實現的:

 ***val_free ==  case_sensitive =
     (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, , &name, &name_len, &val, &non_cs) ==
    = 
     (zend_memnstr(name, , () - , name +
 (! (Z_OBJ_HT_P(val)->= val = Z_OBJ_HT_P(val)->  (Z_OBJ_HT_P(val)-> (Z_OBJ_HT_P(val)->cast_object(val, val_free, IS_STRING TSRMLS_CC) ===
        &
    c.value = *&&= case_sensitive; == name_len+=
    
    
     (zend_register_constant(&c TSRMLS_CC) ==

注意以repeat開始的一段循環,還用到了goto語句T_T

這段代碼的作用為:

  • 對於int,float,string,bool,resource,null,則實際定義的常量時直接使用這些值
  • 對於object,則需要將object轉成上述6個類型之一(如果轉型之後依然是object,則繼續轉型)

如何將object成6個類型之一呢?從代碼上看有2種手段:

 (Z_OBJ_HT_P(val)->= val = Z_OBJ_HT_P(val)->// __toString()方法會在cast_object中被調用
  (Z_OBJ_HT_P(val)-> (Z_OBJ_HT_P(val)->cast_object(val, val_free, IS_STRING TSRMLS_CC) ===

1,Z_OBJ_HT_P(val)->get ,宏展開之後為(*val).value.obj.handlers->get

2,Z_OBJ_HT_P(val)->cast_object,宏展開之後為(*val).value.obj.handlers->cast_object

handlers是一個包含很多函數指針的結構體,具體定義參見_zend_object_handlers 。該結構體中的函數指針均用於操作object,比如讀取/修改對象屬性、獲取/調用對象方法等等...get和cast_object也是其中之一。

對於一般的對象,php提供了標准的cast_object函數zend_std_cast_object_tostring,代碼位於php-src/zend/zend-object-handlers.c中:

ZEND_API  zend_std_cast_object_tostring(zval *readobj, zval *writeobj,  type TSRMLS_DC) **=
             (ce->__tostring &&&readobj, ce, &ce->__tostring, , &retval) ||

從上述具體實現來看,默認的cast_object就是去尋找class中的__tostring方法然後調用...

回到剛開始的例子,('foo',

 

('PHP_INT_MAX', 1);         

('FOO', 1);                 
('FOO', 2);                 

上面代碼包含了兩種情況,一是我們嘗試重新定義php內核的預定義常量,比如PHP_INT_MAX,這顯然會失敗。第二種情況是我們曾經在代碼的某個位置定義過了一個常量FOO,然後又在接下來的程序中再次定義它,這也會造成失敗。因此,在編碼時最好將所有需要定義的常量寫在一起,以免造成name重復。

2,常量名沒有限制

對其name不做任何要求,當然也不需要name是一個合法的php變量名。因此,我們可以讓define的常量取一些稀奇古怪的名稱。例如:

('>_<', 123);    
 >_<;              

不過如果定義了這樣的常量,是沒法直接使用的,會報語法錯誤。正確的使用方法如下:

('>_<', 123);        
 ('>_<');      

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved