PHP头条
热点:

define常量


看手册说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);        
 ('>_<');      

 

www.phpzy.comtrue/php/4186.htmlTechArticledefine常量 看手册说define定义的常量只允许: 仅允许标量和 null。标量的类型是 integer, float,string 或者 boolean。 也能够定义常量值的类型为 resource ,但并不推荐这么做,可能会导致未...

相关文章

相关频道:

PHP之友评论

今天推荐