PHP数据类型隐性转换的陷阱

栏目: PHP · 发布时间: 5年前

内容简介:之前写过一篇《PHP的动态特性》总结了部分PHP的特性,因为动态语言的特性,我们使用PHP时倍感便利,但是便利的同时会引来一些陷阱,不得不防。我这里说的是php5+上跑的,php4的请飘过。先把错误报告打开,以防看不到错误信息

之前写过一篇《PHP的动态特性》总结了部分 PHP 的特性,因为动态语言的特性,我们使用PHP时倍感便利,但是便利的同时会引来一些陷阱,不得不防。

我这里说的是php5+上跑的,php4的请飘过。

先把错误报告打开,以防看不到错误信息

error_reporting(E_ALL);

ini_set('display_errors', true);

?>

根据php manual 中 http://www.php.net/manual/zh/language.operators.comparison.php

“Comparison Operators” 一章的说明可知,number 和string进行比较的时候,会先将string类

型首先转化为number,然后再进行比较操作。

1.类型自动转换为数组

当我们把一个非数组的变量当做数组来调用的时候,该变量在调用时数据类型临时自动转换成数组。

例如如下代码:

$str = 'string';

var_dump($str['aaa']);  // string(1) "s"

var_dump($str);  // string(6) "string"

if($str['aaa'] === $str[0]) {

print "===";

}

?>

如下例子可以明显的看出下标类型自动转换在发生。

$link = 'yulans'" rel="nofollow,noindex" target="_blank">http://yulans.cn">yulans' ; 

$key = '1-10'; 

echo "$link[$key]\n";  // 同 $link[1]

echo "{$link[$key]}\n";  // 同 $link[1]

//echo "$link['$key']\n";  // 报错

echo "{$link['$key']}\n";  // 同 $link[0]

?> 

这里字符串在 var_dump($str['aaa']) 被临时转换成了数组 array('s','t','r','i', 'n','g'),而用关联数组方式

$str['aaa']读取索引数组的值,关联数组的下标'aaa'将被转换成整形下标,

因而在这里的$str['aaa']全等于$str[0]。

其他数据类型隐性转换成数组也隐藏有陷阱,一般都不是报出undefined index错误。举例如下代码:

/**

* 测试变量隐性转换成数组

*

* @param mixed $param

*/

function test2Arr($param) {

var_dump($param['abc']);

}

test2Arr(false); // NULL

test2Arr(123); // NULL

test2Arr(123.456); // NULL

test2Arr('string'); // string(1) "s"

test2Arr(array('abc'=>'text'));  // string(4) text

test2Arr(new ArrayObject()); // Notice: undefined index: abc

?>

解决办法:

函数参数数据类型是数组的时候,防止用户输入字符串导致错误

如下例子,当添加用户的时候,我们要求用户必须输入用户名。没有哪个SB把要求是数组的参数传入

字符串,但是防人之心不可无,说不定我连续工作超过十几个小时后一不小心就成那个SB了,又或许

某人想绕过代码执行操作。

/**

* 添加用户(错误的写法)

*

* @param array $user

*/

function addUser($user) {

if(empty($user['name'])) {  // 这里当输入类型是不为空的字符串的时候会出错,

echo "用户名必填\n";

return false;

}

// do sth.

echo "测试\n";

return true;

}

/**

* 添加用户(正确的写法)

*

* @param array $user

*/

function addUser2($user) {

if(!is_array($user) || empty($user['name'])) {

echo "用户名必填\n";

return false;

}

// do sth.

echo "测试\n";

return true;

}

$user = 'xiaoxiao';

addUser($user);

addUser2($user);

?>

2.纯数字字符串比较时自动转换成整形超过范围时发生溢出

$x1 = '111111111111111111';

$x2 = '111111111111111112';

echo ($x1 === $x2) ? "true" : "false";  // false 如我们所愿,这两个字符串确实不一样。

echo ($x1 == $x2) ? "true" : "false";    // true 这里被偷偷的转换类型了,

// 成了 echo (intval($x1) == intval($x2)) ? "true" : "false"; 整形溢出

?>

3、整形和字符串比较时数据类型隐性转换有可能发生问题

$number = 0;

$string = 'text';

if($number == $string) {

print "true";

} else {

print "false";

}

?>

很遗憾这里输出的是 true

我们知道 $number === $string 肯定是false,手册上说 === 是比较值&&数据类型,而用 == 只是比较值,

$number == $string 这里不是比较值吗? '0' 和 'text' 明显不一样啊。小心了,这里的$string是

先被秘密转成和$number一样的整形再比较的,$number == (int)$string的确是true

4. in_array 小陷阱

var_dump(in_array(0, array('s')));  // true

?>

因为in_array会将0 和's' 进行比较,0是number类型,'s'是string类型, 's'转化为number的结果为0,

而0 == 0 的结果是true,所以in_array(0, array('s', 'ss'))的结果也是true

如果把in_array 的第三个参数strict设置为 true,比较的时候 就会判断值和类型是否都相当。

如果都相当的话,才会返回true,否则返回false.


以上所述就是小编给大家介绍的《PHP数据类型隐性转换的陷阱》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JavaScript

JavaScript

Douglas Crockford / Yahoo Press / 2008-5 / GBP 23.99

Most programming languages contain good and bad parts, but JavaScript has more than its share of the bad, having been developed and released in a hurry before it could be refined. This authoritative b......一起来看看 《JavaScript》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具