摘要:現(xiàn)在我們已經(jīng)可以從符號(hào)表中獲取用戶(hù)在PHP語(yǔ)言里定義的變量了,是該做點(diǎn)其它事的時(shí)候了,舉個(gè)比例,比如給它來(lái)個(gè)類(lèi)型轉(zhuǎn)換 。想想C語(yǔ)言中的類(lèi)型轉(zhuǎn)換細(xì)則,你的頭是不是已經(jīng)大了?但是變量的類(lèi)型轉(zhuǎn)換就是如此重要,如果沒(méi)有,那我們的代碼就會(huì)是下面這樣了:void display_zval(zval *value) { s
現(xiàn)在我們已經(jīng)可以從符號(hào)表中獲取用戶(hù)在PHP語(yǔ)言里定義的變量了,是該做點(diǎn)其它事的時(shí)候了,舉個(gè)比例,比如給它來(lái)個(gè)類(lèi)型轉(zhuǎn)換 。想想C語(yǔ)言中的類(lèi)型轉(zhuǎn)換細(xì)則,你的頭是不是已經(jīng)大了?但是變量的類(lèi)型轉(zhuǎn)換就是如此重要,如果沒(méi)有,那我們的代碼就會(huì)是下面這樣了:
void display_zval(zval *value) { switch (Z_TYPE_P(value)) { case IS_NULL: /* 如果是NULL,則不輸出任何東西 */ break; case IS_BOOL: /* 如果是bool類(lèi)型,并且true,則輸出1,否則什么也不干 */ if (Z_BVAL_P(value)) { php_printf("1"); } break; case IS_LONG: /* 如果是long整型,則輸出數(shù)字形式 */ php_printf("%ld", Z_LVAL_P(value)); break; case IS_DOUBLE: /* 如果是double型,則輸出浮點(diǎn)數(shù) */ php_printf("%f", Z_DVAL_P(value)); break; case IS_STRING: /* 如果是string型,則二進(jìn)制安全的輸出這個(gè)字符串 */ PHPWRITE(Z_STRVAL_P(value), Z_STRLEN_P(value)); break; case IS_RESOURCE: /* 如果是資源,則輸出Resource #10 格式的東東 */ php_printf("Resource #%ld", Z_RESVAL_P(value)); break; case IS_ARRAY: /* 如果是Array,則輸出Array5個(gè)字母! */ php_printf("Array"); break; case IS_OBJECT: php_printf("Object"); break; default: /* Should never happen in practice, * but it's dangerous to make assumptions */ php_printf("Unknown"); break; } }
看完上面的代碼,你是不是有點(diǎn)似曾相識(shí)的感覺(jué)?o(∩∩)o...哈哈,和直接<?php echo $foo;?>這個(gè)簡(jiǎn)單到極點(diǎn)的php語(yǔ)句來(lái)比,上面的實(shí)現(xiàn)算是天書(shū)了。當(dāng)然,真正的環(huán)境并沒(méi)有這么囧,內(nèi)核中提供了好多函數(shù)專(zhuān)門(mén)來(lái)幫我們實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換的功能,你需要的只是調(diào)用一個(gè)函數(shù)而已。這一類(lèi)函數(shù)有一個(gè)統(tǒng)一的形式:convert_to_*()
//將任意類(lèi)型的zval轉(zhuǎn)換成字符串 void change_zval_to_string(zval *value) { convert_to_string(value); } //其它基本的類(lèi)型轉(zhuǎn)換函數(shù) ZEND_API void convert_to_long(zval *op); ZEND_API void convert_to_double(zval *op); ZEND_API void convert_to_null(zval *op); ZEND_API void convert_to_boolean(zval *op); ZEND_API void convert_to_array(zval *op); ZEND_API void convert_to_object(zval *op); ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC); #define convert_to_string(op) if ((op)->type != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); }
這里面有兩個(gè)比較特殊,一個(gè)就是convert_to_string其實(shí)是一個(gè)宏函數(shù),調(diào)用的另外一個(gè)函數(shù);第二個(gè)便是沒(méi)有convert_to_resource()的轉(zhuǎn)換函數(shù),因?yàn)橘Y源的值在用戶(hù)層面上,根本就沒(méi)有意義,內(nèi)核不會(huì)對(duì)它的值(不是指那個(gè)數(shù)字)進(jìn)行轉(zhuǎn)換。
好了,我們用php的echo的時(shí)候會(huì)先把變量轉(zhuǎn)換成字符串,但是我們看見(jiàn)convert_to_string的參數(shù)是zval*的,你是不是開(kāi)始擔(dān)心在進(jìn)行數(shù)據(jù)轉(zhuǎn)換時(shí)破壞了原來(lái)數(shù)據(jù)的值?而我們<?php $a=intval($b);?>并不會(huì)破壞$b的值。把原來(lái)的值破壞掉的做法絕對(duì)不是一個(gè)好主意,內(nèi)核中在echo一個(gè)變量的時(shí)候也不是這樣做的。在下一章,我們將知道怎樣便可以在不損壞原變量值的情況下,進(jìn)行convert_to_類(lèi)操作。