PHP開發中常見的坑

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章