PHP判断空值以及变量和数值作比较
文章目录
- 环境
- 总结
- 判断空值
- 其它
- 判断数组的键是否存在
- 判断变量是否存在
- `??` 运算符
- 变量和0比较
环境
- PHP 8.2.12
- Windows 11 专业版
总结
如果不想看详细内容,可以直接看总结:
- 最常用、最推荐的方法是
isset()
,它是真正的判“空”:- 要么变量不存在
- 要么变量的值是null
- 如果把条件放宽,把0、false、空字符串、空数组也看做空值,那么可使用
empty()
方法来判别 isset()
的变体是$x !== null
,但是对于不存在的变量,后者会报出warningUndefined variable
,因此不推荐empty()
的变体是$x
,但是对于不存在的变量,后者会报出warningUndefined variable
,因此不推荐array_key_exists()
可以判断数组里是否存在某个键(值为null也算存在)get_defined_vars()
结合array_key_exists()
,可以精细判断某个变量是否存在(值为null也算存在)$x ?? 123
相当于isset($x) ? $x : 123
,是后者的简写- 变量和数值作比较时,一定要确保变量存在,而且是数值类型的。注意如果用
is_numeric()
,会兼容一部分字符串 - 反之,如果直接拿变量和数值作比较,则即使变量不存在,或者为null值,或者为非数值类型,也能比较(变量不存在时会报一个warning),但结果可能出乎意料,因此强烈不推荐
判断空值
PHP在判断空值时,大概有以下4种情况:
- 变量不存在,或已被
unset()
- 变量值为
null
- 变量值为
0
、''
、false
、空数组等值 - 正常有值的变量
变量不存在,或已被 unset() | null | 0,空字符串,false,空数组 | 其它值 | |
---|---|---|---|---|
isset($x) | false | false | true | true |
!empty($x) | false | false | false | true |
$x !== null | false with warning | false | true | true |
$x | false with warning | false | false | true |
其它
判断数组的键是否存在
前面提到的方法,对于“变量不存在”和“变量存在且值为null”这两种情况,基本上是不区分的,因为绝大多数情况下,都没有必要区分。
不过对于数组,有时可能需要判断某个键是否存在,比如:
$arr1 = array('x'=>123, 'y'=>null);
$arr2 = array('x'=>123);
$arr1
比 $arr2
多了一个键 y
(虽然其值是null)。
如何判断这种情况呢?答案是用 array_key_exists()
:
array_key_exists('y', $arr1)
:truearray_key_exists('y', $arr2)
:false
判断变量是否存在
同理,回过头来,我们也可以分辨“变量不存在”和“变量存在且值为null”这两种情况。方法是先用 get_defined_vars()
获取所有变量(得到一个数组),然后通过 array_key_exists()
判断指定键是否存在:
$arr = get_defined_vars();if (array_key_exists("x", $arr)) { // falseecho "x is defined";
} else {echo "x is not defined";
}$x = null;$arr = get_defined_vars();if (array_key_exists("x", $arr)) { // trueecho "x is defined";
} else {echo "x is not defined";
}
??
运算符
先看一个例子:
$x ?? 123
它的功能是:如果 $x
存在且不为null,则返回 $x
,否则返回 123
。
可见,该代码等价于以下的三目运算:
isset($x) ? $x : 123
可以把前者看做是后者的简写。
因为代码中会经常遇到取值时,需要先判断是否为空值的情况,可以用 if...else...
或者三目运算符,而 ??
运算符简化了代码,更加一目了然。
跑个题:在SQL语言中,比如Db2和MySQL,有 coalesce()
函数,也实现了类似的功能,比如:
select coalesce(c1, 0) as c1 from t1
coalesce()
的功能是:如果第一个参数不是null则返回第一个参数,否则返回第二个参数。
变量和0比较
另一种常见的场景是,变量和0的比较,比如:
if ($teamid > 0)......
上面的写法不够严谨:
- 变量可能并不存在
- 变量可能是null值
- 变量可能是非数值类型
显然,更严谨的做法是,先确定变量存在而且是数值,然后再和0作比较:
if (isset($x) && (is_int($x) || is_float($x)) && $x > 0)
或者:
if (isset($x) && is_numeric($x) && $x > 0)
前者比较严格,判断变量的类型是否为int或float,而后者较为宽松,对字符串也有一定的容忍。
对字符串的判别,比如:
is_numeric('123')
:true,123is_numeric('1e3')
:true,1000is_numeric(' 123 ')
:true,123is_numeric('0123')
:true,123 (注:不能当作8进制,而是直接忽略前面的0)is_numeric('0xFF')
:false (注:不识别16进制,但在早期PHP版本中,可能是true)is_numeric('123abc')
:false (不识别数字和字母的混合体)
注意,即使 is_numeric()
测试结果是false,也可以强转为数值,比如:
(int) '0123'
:123(不能当作8进制,而是直接忽略前面的0)(int) '0xFF'
:0 (不识别16进制)(int) '123abc'
:123(int) 'xyz'
:0
转换规则是,从字符串开头开始,找数字或合法的字符(比如 e
),一直到不符合要求为止,然后把可以转换的部分转换为数值。如果从一开头就不可转换,则转换结果为0。
关于字符串到数值的类型转换,可参见我另一篇文档: https://blog.csdn.net/duke_ding2/article/details/149110312
总之,如果不做判断,直接拿变量和0做对比,很可能会出现非期望的结果。以下面的代码为例:
if ($x > 0)
......
变量不存在,或已被 unset() | null | 0 | 空字符串 | ‘xyz’ | false | 空数组 | 其它值 | |
---|---|---|---|---|---|---|---|---|
$x > 0 | false with warning | false | false | false | true | false | true | 视情况而定 |
$x < 0 | false with warning | false | false | true | false | false | false | 视情况而定 |
$x == 0 | true with warning | true | true | false | false | true | false | 视情况而定 |
$x != 0 | false with warning | false | false | true | true | false | true | 视情况而定 |
$x === 0 | false with warning | false | true | false | false | false | false | 视情况而定 |
$x !== 0 | true with warning | true | false | true | true | true | true | 视情况而定 |
总结:把变量当作数值和0比较时:
- 变量不存在:0,但在严格比较时,不是0。此外,会报一个warning
- null:0,但在严格比较时,不是0
- 0:0,严格比较时,也是0(废话)
- 空字符串:一个小于0的数
- false:0,但在严格比较时,不是0
- 空数组:一个大于0的数
- 其它值:视情况而定
可见,如果直接拿变量和0作比较,会产生很多意想不到的结果。因此,一定要确保变量非空且是数值类型,才能和数值做比较。