PHP開發中常見的坑
1、switch/case
使用 switch 語句可以避免冗長的 if..elseif..else 代碼塊。但是一不小心,就會掉坑裏。
1)當case爲一個範圍時
使用 0 < $num < 50,這種方式是不可以的,所以要用 0 < $num && $num < 50的方式,拆開寫纔可以
1 <?php 2 $a = 89; 3 switch ($a) { 4 case ($a < 60): 5 echo '不及格'; 6 break; 7 case ($a < 80): 8 echo '中等'; 9 break; 10 case ($a < 90): 11 echo '良'; 12 break; 13 default: 14 echo '優秀'; 15 break; 16 } 17 18 // 輸出結果 19 // 良
2)當switch表達式中的值爲0
1 <?php 2 $a = 0; 3 switch ($a) { 4 case ($a < 60): 5 echo '不及格'; 6 break; 7 case ($a < 80): 8 echo '中等'; 9 break; 10 case ($a < 90): 11 echo '良'; 12 break; 13 default: 14 echo '優秀'; 15 break; 16 } 17 // 輸出結果 18 // 優秀
這個地方,如果按照if...else的思維,滿足第一個case語句,然後直接輸出:不及格。但是實際情況輸出的是:優秀
分析:switch/case跟if...else條件語句的區別是,switch表達式的值是與case語句中的值作匹配的,並不是像if條件中的只要是true就執行
php裏面的switch會轉換case類型,使用的時候一定要注意。
3)switch/case作的是鬆散比較
1 <?php 2 $string = "2string"; 3 4 switch ($string) { 5 case 1: 6 echo "this is 1"; 7 break; 8 case 2: 9 echo "this is 2"; 10 break; 11 case '2string': 12 echo "this is a string"; 13 break; 14 } 15 16 // 輸出結果 17 // this is 2
注意:
1) switch中使用“==”進行比較的時候,尤其是string和int值比較時,會將字符串強轉爲int類型
2) 在使用switch的時候,應該保證比較值和每個case的類型一致,否則就可能出現不可預計的錯誤
2、in_array
bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )
說明:在 haystack 中搜索 needle,如果沒有設置 strict 則使用 寬鬆 的比較。如果第三個參數 strict 的值爲 true,則 in_array 函數還會檢查 needle 的 類型 是否和 haystack 中的相同。
1 <?php 2 3 $arr = [0, 1]; 4 $a = '1test'; 5 if (in_array($a, $arr)) { 6 echo 111; 7 } else { 8 echo 222; 9 } 10 11 // 輸出結果 12 // 111
可以看到,這裏$a = ‘1test’,在校驗過程中,$a由字符串轉成了int類型,繞過了in_array中的校驗。
解決方法有三種:
1)將參數$a類型轉換成整型: $a=(int)$a;
2)in_array中的數組內value改成字符串類型:in_array($a,['1','2'])
3)in_array中第三個參數 strict 的值設爲 true:in_array($a,[1,2],true)
1 <?php 2 3 $arr = [0, 1]; 4 $a = '1a'; 5 if (in_array($a, $arr,true)) { 6 echo 111; 7 } else { 8 echo 222; 9 } 10 11 // 輸出結果 12 // 222
另外,補充一下,關於字符串/字符和數字進行大小比較時,會將字符串轉成數字,
1)PHP 8.0 之前,首先系統嘗試將此字符串/字符轉換爲整型/浮點型,然後進行比較,如'12bsd'轉型爲12,'a'轉型爲0
2)PHP 8.0 比較數字字符串(numeric string)時,會按數字進行比較。 不是數字字符串時,將數字轉化爲字符串,按字符串比較。
1 <?php 2 3 // PHP 7 4 0 == 'foobar'; // true 5 6 // PHP 8 7 0 == 'foobar';// false
3、關於if else容易迷惑的問題
1 <?php 2 $a = true; 3 if ($a) { 4 echo "true".PHP_EOL; 5 } else label: { 6 echo "false"; 7 } 8 9 // 輸出結果 10 // true 11 // false
在zend_language_parser.y中:
1 statement: 2 ... 3 | T_DO statement T_WHILE '(' expr ')' ';' {...} 4 | T_SWITCH '(' expr ')' switch_case_list {...} 5 | T_STRING ‘:’ { $$ = zend_ast_create(ZEND_AST_LABEL, $1); }
這裏可以看到,do while, switch 都會聯合他們的body歸約爲statement(語句),但標籤(label)有點不同,”label :”本身會歸約爲一條statement, 這就導致了這個看起來比較迷惑的問題的出現,他本質上就變成了:
1 <?php 2 $a = true; 3 if ($a) { 4 echo "true".PHP_EOL; 5 } else { 6 label: ; //單獨的一條語句 7 } 8 echo "false"; 9 10 // 輸出結果 11 // true 12 // false
參考鏈接:https://www.laruence.com/2020/07/09/6015.html