在日常 PHP 编程中,我们经常使用 unset() 删除数组中的元素,例如:
$arr = [ 'a', 'b', 'c' ];
unset($arr[1]);
print_r($arr);
很多人以为执行后数组会变成:
['a', 'c']
但实际上输出结果是:
Array
(
[0] => a
[2] => c
)
可以看到索引 没有重新排列,原来的下标 [1] 被删除后,PHP 并不会自动调整后续元素的索引。
PHP 的数组是 有序哈希表(Ordered Hash Table),
既可以用作索引数组,也可以用作关联数组。
当你执行:
unset($arr[1]);
PHP 实际上只是从哈希表中 移除了该键对应的项,
但不会重新分配其它键(即不会重排)。
这样设计的好处是:
删除元素开销小;
维持键的稳定性;
保证关联数组不被破坏。
这种行为在某些场景下会导致逻辑错误:
❌ 示例 1:使用 for 循环遍历
$arr = [ 'a', 'b', 'c' ];
for ($i = 0; $i < count($arr); $i++) {
if ($arr[$i] === 'b') unset($arr[$i]);
}
print_r($arr);
输出结果:
Array
(
[0] => a
[2] => c
)
由于索引跳跃,$arr[1] 被删除后,count() 返回 3,但 $arr[1] 不存在。
如果后续逻辑依赖索引顺序(比如 $arr[$i+1]),就会出错。
✅ 方案 1:使用 array_values() 重排索引
$arr = [ 'a', 'b', 'c' ];
unset($arr[1]);
$arr = array_values($arr);
print_r($arr);
输出:
Array
(
[0] => a
[1] => c
)
array_values() 会重新生成从 0 开始的连续索引,非常适合处理纯数字索引数组。
✅ 方案 2:使用 foreach 遍历 + unset
$arr = [ 'a', 'b', 'c' ];
foreach ($arr as $key => $value) {
if ($value === 'b') unset($arr[$key]);
}
print_r($arr);
PHP 的 foreach 遍历使用内部指针,即使当前元素被删除,也不会影响循环行为。
但仍然不会重排索引。
如果后续需要连续索引,可再执行:
$arr = array_values($arr);
✅ 方案 3:反向遍历删除(for 循环)
$arr = [ 'a', 'b', 'c' ];
for ($i = count($arr) - 1; $i >= 0; $i--) {
if ($arr[$i] === 'b') unset($arr[$i]);
}
print_r($arr);
这种写法在删除多个元素时能保证不会“跳过”元素。
✅ 方案 4:用关联键(推荐用于复杂数据结构)
如果你的数据是关联数组(如数据库记录),
可以直接用键值操作,避免索引问题:
$db = [
['id' => 1, 'name' => 'A'],
['id' => 2, 'name' => 'B'],
['id' => 3, 'name' => 'C']
];
// 重新索引成 id=>item
$map = [];
foreach ($db as $item) {
$map[$item['id']] = $item;
}
// 删除指定 id
unset($map[2]);
print_r(array_values($map));
输出:
Array
(
[0] => Array ( [id] => 1 [name] => A )
[1] => Array ( [id] => 3 [name] => C )
)
场景 是否重排 适用情况 推荐度
unset() 直接删除 ❌ 否 临时删除,不依赖索引 ⭐
array_values() 重排 ✅ 是 删除后需保持连续索引 ⭐⭐⭐⭐
foreach + unset() ❌ 否 逻辑删除但不重排 ⭐⭐⭐
反向 for 删除 ❌ 否 控制删除顺序 ⭐⭐
关联键删除 ✅ 无影响 有唯一 ID 键的数组
$a['modulesn'] = "0542509004725";
$b = "00542509004725";
一个是 以 0 开头,另一个是 以 00 开头。
按理说用 != 应该返回 true(不相等),但你说结果是 false(相等)。
原因:PHP 的弱类型比较(类型转换问题)
在 PHP 里,!=、== 会触发 弱类型比较:
如果两个字符串看起来都是 数字字符串,PHP 会把它们转换成数字再比较。
"0542509004725" 和 "00542509004725" 都会被转换成 542509004725(整数)。
转换后它们相等,所以 != 返回 false。
验证
var_dump((int)"0542509004725"); // int(542509004725)
var_dump((int)"00542509004725"); // int(542509004725)
结果一样。
解决办法
如果你想比较字符串本身,而不是数值:
用 全等比较 !== 或 ===
var_dump($a['modulesn'] !== $b); // true
或者强制用 字符串比较函数
var_dump(strcmp($a['modulesn'], $b) !== 0); // true
建议:凡是涉及可能带前导 0 的数据(比如条码、序列号、工号),一定要用 === 来比较,不要用 == 或 !=。
max_input_vars 表示接受多少 输入的变量(限制分别应用于 $_GET、$_POST 和 $_COOKIE 超全局变量) 指令的使用减轻了以哈希碰撞来进行拒绝服务攻击的可能性。 如有超过指令指定数量的输入变量,将会导致 E_WARNING 的产生,更多的输入变量将会从请求中截断。
; How many GET/POST/COOKIE input variables may be accepted
; max_input_vars = 1000
max_input_vars = 10000PHP中的new static()是一个非常实用的语法,它可以帮助我们实现基于对象的一个非常重要的特性——多态性。具体来说,new static()可以在父类中创建一个子类的实例,实现不同子类之间的调用。下面,我将深入介绍new static()语法及其用法。 阅读全文→