2016-09-22 62 views
0

我最近創建了一個答案的SO,我開始意識到,我認爲是在PHP中一個奇怪的行爲,我從來沒有因發現我的(以下)的編碼風格:concat運算符和浮點標識符'。'的優先級。 (T_CONSTANT_ENCAPSED_STRING,T_DNUMBER)

$var = 1; 
echo "test string ". $var+1 ." example"; 

這工作正常,但是如果我刪除1.之間的空間:

echo "test string ". $var+1." example"; 

它會給我T_CONSTANT_ENCAPSED_STRING語法錯誤,並且在這種情況下,期待一個','或​​3210這是相當不正確。

是的..它會像這樣:

echo "test string ".($var+1)." example"; 

我與此遇到的問題是,該錯誤消息是,它並不能明確反映的是什麼潛在的問題希望大多數其他消息直接指向正確的地方。

雖然我起初並沒有想到浮動點是這個原因我仍然有一個很難理解爲什麼浮動運營商在以下情況下優先於毗連運算:

var_dump(.1, 1, 1., 1.0); 
var_dump(1.."a", "a"..1, 1.0."a"); 

浮動(0.1),INT(1)中,浮子(1),浮子(1)
串(2) 「1A」,串(4) 「A0.1」,串(2) 「1A」

現在我明白算術運算符應該在字符串操作之前進行,但這裏只是我的一部分不明白:

".11."應該指出.是一個毗連運算和1.1應該指出.是一個浮動的標識符。相反,他們都給解析錯誤。

PHP是不挑剔的語言時,它涉及到的變量類型:

var_dump(1 + 1.); // float(2) 
var_dump(1. + 1); // float(2) 

您可以簡單地使用+ 1添加到一個浮動的,爲什麼解析1.作爲浮動呢?解析錯誤發生在下一個令牌上,它在期望一個數字,甚至不允許它是一個concat操作符。

所以我的問題是,爲什麼PHP詞法分析器和扔這麼重視浮動識別如果echo 1."test"將輸出1test可以打破它現有的代碼?

我編輯了這個問題,以澄清我的意思,首先是由於我得到的負面代表。目前公認的答案仍然是非常有效的,因爲我需要一種方法來驗證PHP代碼,而無需使用eval()

+5

那是因爲'PHP'期待一個浮點因爲你旁邊的'integer'點。字符串「1.」不是有效的浮點數,因此錯誤爲 – DarkBee

+0

https://eval.in/646594。這個'$ var + 1.'被視爲php中的類型轉換,而母雞缺少一個'.'。錯誤被給出 –

+0

我的意思是說''var + 1.' worka作爲類型轉換,並且在解析器獲取「example」(字符串)之後,所以它給出了錯誤 –

回答

2

1.指浮點數1.0。所以,你寫的是什麼lexed爲:

echo "test string " . $var + 1.0 " example"; 

字符串" example"T_CONSTANT_ENCAPSED_STRING令牌。解析器不會在浮點數之後立即進行分析。

你可以用token_get_all()檢查:

php > var_export(token_get_all('<?php echo "test string ".$var+1." example";')); 
array (
    0 => 
    array (
    0 => 379, 
    1 => '<?php ', 
    2 => 1, 
), 
    1 => 
    array (
    0 => 328, 
    1 => 'echo', 
    2 => 1, 
), 
    2 => 
    array (
    0 => 382, 
    1 => ' ', 
    2 => 1, 
), 
    3 => 
    array (
    0 => 323, 
    1 => '"test string "', 
    2 => 1, 
), 
    4 => '.', 
    5 => 
    array (
    0 => 320, 
    1 => '$var', 
    2 => 1, 
), 
    6 => '+', 
    7 => 
    array (
    0 => 318, 
    1 => '1.', 
    2 => 1, 
), 
    8 => 
    array (
    0 => 323, 
    1 => '" example"', 
    2 => 1, 
), 
    9 => ';', 
) 
php > print token_name(318); 
T_DNUMBER 
php > print token_name(323); 
T_CONSTANT_ENCAPSED_STRING 

注意1.顯示爲一個令牌,318T_DNUMBER,雙號)。

+0

所以優先級似乎是應用'.'將值轉換爲算術(不是運算符)的浮點數,所以'+'確實有優先權。我永遠不會期望像通常那樣引起這個問題的花車,我會直接將它們捕獲到變量中.. – Xorifelse

+0

@Xorifelse這裏沒有優先級問題。當程序在語法上正確時,運算符的優先級被應用,這裏存在語法錯誤。 '1.'是一個浮點數,不涉及字符串連接。 '1 .'是一個整數,後跟字符串連接運算符。 '1.「abc」'是一個數字後跟一個字符串,它們之間沒有操作符(語法錯誤)。對於'1'也是一樣。 「ABC」'。 '1。「abc」'是一個數字,後面跟着一個串聯運算符,後跟一個字符串。對於'1'也是一樣。 「abc」' – axiac

+0

@axiac這就是我所說的「(不是操作符)」,但是'1.''和'1.1'之間有明顯的區別,其中'1.''表示'.'是一個運營商和'1.1'將使它成爲一個浮動。因此,PHP解釋器的近視困惑,但是可以理解。 – Xorifelse

0

讓我告訴你,即使你的聲明:
echo "test string ". $var+1 ." example";
可能無法正常工作。 它可能會打印1 example而不是test string 2 example

你還可以找到一個意想不到的結果,這是有用

var_dump(1) gives `int 1` and 
var_dump(1.) gives `float 1` and as expected 
var_dump(1.0) gives `float 1` as answer 

原因:
"test string ". $var+1 ." example";
第一「test string」(字符串變量)將連接到$var,使結果string 1 (字符串)然後它被添加(不級聯)到1使php更改**string 1**(字符串)的類型爲int因此它將會e 0,然後加到1導致1(0 + 1 = 1)。然後1(從int到字符串轉換再次)被添加到example(一個字符串)導致1 example(一個字符串)。

使用圓括號避免這種類型的變化 在上次聲明中enter code here

echo "test string ".($var+1)." example";