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

 

posted @ 2021-01-26 19:14  欢乐豆123  阅读(122)  评论(0编辑  收藏  举报