PHP弱数据类型导致的缺陷和解决方案

一、弱数据类型导致的缺陷

PHP是弱数据类型语言、因此,在进行 == 判断时,会存在一些隐患。

1、Hash 比较缺陷

如果 Hash 值以 0e 开头,当与数字比较时,就会被解析为 0 * 10ⁿ,会被判断与0相同。

解决方案:使用 === 进行全等判断

2、数字比较缺陷

PHP中,允许比较的最大值为 PHP_INT_MAX,也就是9223372036854775807,如果超出这个范围,则比较时将可能得不到正确的结果。

<?php
declare(strict_types = 1);

$intOne = 92233720368547758072;
$intTwo = 92233720368547758073;
if ($intOne === $intTwo) {
    echo '相等';
} else {
    echo '不相等';
}

得到的结果是‘相等’,因为比较时超出了PHP最大范围,因此只比较到最大范围截止,出现了不理想的结果。所以比较时,注意限定要比较的数字允许最大范围。

3、类型自动转换缺陷

<?php
declare(strict_types = 1);

$a = 22;
$b = '22cd5';
echo $a == $b ? '相等' : '不相等';

得到的结果是相等。

第一种解决方案:使用 === 进行判断

第二种解决方案:在比较前,对需要比较的变量进行类型判断,接收参数时,也强制数据类型。

<?php
declare(strict_types = 1);

class Test
{
    public function operate(int $firstNum, int $secondNum)
    {
        // 业务逻辑处理
    }
}

利用PHP7的新特性严格模式,做强类型要求。

4、switch 比较缺陷

<?php
declare(strict_types = 1);

$type = '2sec';

switch ($type) {
    case 1 :
        echo 'this is 1';
        break;
    case 2 :
        echo 'this is 2';
        break;
    default :
        echo 'this is default';
        break;
}

得到的结果是 ‘this is 2’, $type在比较时,被自动转换成其他了。

解决方案:在比较前对参数进行校验。

<?php
declare(strict_types = 1);

$type = '2sec';
if (!is_numeric($type) || !in_array($type, [1, 2])) {
    echo '类型只能是1或者2,这里是错误抛出';
}
switch ($type) {
    case 1 :
        echo 'this is 1';
        break;
    case 2 :
        echo 'this is 2';
        break;
    default :
        echo 'this is default';
        break;
}

5、数组比较缺陷

在使用 in_array 或者 array_search时,第三个参数严格模式设置为true。

<?php
declare(strict_types = 1);

$type = '2sec';

// 没使用严格判断模式,得到的结果是合法
if (!in_array($type, [1, 2, 3])) {
    echo '不合法';
} else {
    echo '合法';
}

// 使用了严格模式判断,得到的结果是不合法
if (!in_array($type, [1, 2], true)) {
    echo '不合法';
}