PHP 的类型转换是比较方便的,但是越是容易使用的东西,底层的实现越是复杂,而且在使用中像我这样的新手也往往不清楚转换后的结果到底是什么。有时候,对于 Java 这种强类型的语言,使用的时候需要强制进行转换,这样多半转换后的结果是可以预料的,至少自己是想这么做的。
通过实例看转换
写个关于 PHP 类型转换的代码测试一下吧,看看大家是否能知道输出结果。把 各种数据类型 都转换为 字符串类型试试。
$var=false; echo'$var:', $var, "\r\n"; $var=null; echo'$var:', $var, "\r\n"; $var=true; echo'$var:', $var, "\r\n"; $var=1; echo'$var:', $var, "\r\n"; $var=1.1; echo'$var:', $var, "\r\n"; $var1=&$var; echo'$var:', $var1, "\r\n"; $var1='string111'; echo'$var:', $var1, "\r\n"; $var= [1, 2, 3]; echo'$var:', $var, "\r\n"; classObj{ private$field; } $var=newObj(); echo'$var:', $var, "\r\n";
代码很简单,大家可以猜猜输出结果,然后再和运行结果比对一下,运行结果如下:
$ php string.php $var: $var: $var:1 $var:1 $var:1.1 $var:1.1 $var:string111 $var: Notice: Array to string conversion in C:\Users\Administrator\Desktop\string.php on line 24Call Stack: 0.0010 4055681. {main}() C:\Users\Administrator\Desktop\string.php:0 Array $var: Catchable fatal error: Object of class Obj could not be converted to string in C :\Users\Administrator\Desktop\string.php on line 32Call Stack: 0.0010 4055681. {main}() C:\Users\Administrator\Desktop\string.php:0
不知道是否实际的运行结果和猜测的结果是否一致。
PHP 源码中各类型转换为字符串类型的处理
对于各种类型之间的赋值,并转换为字符串,使用真的是非常的方便。但是,实际的功劳都是 PHP 底层的复杂处理。看一下关于各种类型转换为字符串类型的源代码的处理。
ZEND_APIzend_string*ZEND_FASTCALL_zval_get_string_func(zval*op) /* {{{ */{ try_again: switch (Z_TYPE_P(op)) { caseIS_UNDEF: caseIS_NULL: caseIS_FALSE: returnZSTR_EMPTY_ALLOC(); caseIS_TRUE: returnZSTR_CHAR('1'); caseIS_RESOURCE: { charbuf[sizeof("Resource id #") +MAX_LENGTH_OF_LONG]; intlen; len=snprintf(buf, sizeof(buf), "Resource id #"ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op)); returnzend_string_init(buf, len, 0); } caseIS_LONG: { returnzend_long_to_str(Z_LVAL_P(op)); } caseIS_DOUBLE: { returnzend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(op)); } caseIS_ARRAY: zend_error(E_NOTICE, "Array to string conversion"); returnzend_string_init("Array", sizeof("Array")-1, 0); caseIS_OBJECT: { zvaltmp; if (Z_OBJ_HT_P(op)->cast_object) { if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_STRING) ==SUCCESS) { returnZ_STR(tmp); } } elseif (Z_OBJ_HT_P(op)->get) { zval*z=Z_OBJ_HT_P(op)->get(op, &tmp); if (Z_TYPE_P(z) !=IS_OBJECT) { zend_string*str=zval_get_string(z); zval_ptr_dtor(z); returnstr; } zval_ptr_dtor(z); } zend_error(EG(exception) ?E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name)); returnZSTR_EMPTY_ALLOC(); } caseIS_REFERENCE: op=Z_REFVAL_P(op); gototry_again; caseIS_STRING: returnzend_string_copy(Z_STR_P(op)); EMPTY_SWITCH_DEFAULT_CASE() } returnNULL; } /* }}} */
从上面的源码中可以看出,对于类型的转换,PHP 底层的源码使用了 switch ... case 的结构,在进行转换的时候需要对逐个的类型进行匹配后,再进行转换。当然,从源码的角度去看待上面的 PHP 类型转换的代码就非常的清晰明了了。
最后
读 PHP 的源码有一段时间了,进度比较慢,说实话,对于写 PHP 的代码没有什么提高,或者对我来说没有遇到什么让我提高的地方。单纯的出于对知识求甚解的原因吧。