今天测试反馈了个异常行为,具体是买多个商品最后会漏掉最后一个商品
php 版本 7.0,简化后代码如下:
$itemIdAndQuantityListJson = '[{"itemId":11215,"quantity":10},{"itemId":10234,"quantity":1},{"itemId":10444,"quantity":1},{"itemId":10447,"quantity":1},{"itemId":10448,"quantity":1},{"itemId":10449,"quantity":1}]';
/** @var array $itemIdAndQuantityList */
$itemIdAndQuantityList = json_decode($itemIdAndQuantityListJson, true);
try {
/** @var int[] $itemIdList */
$itemIdList = [];
foreach ($itemIdAndQuantityList as &$itemIdAndQuantity) {
$itemIdAndQuantity["itemId"] = intval($itemIdAndQuantity["itemId"]);
if (!$itemIdAndQuantity["itemId"]) {
throw new \RuntimeException("Parameters fault",15);
}
if (in_array($itemIdAndQuantity["itemId"], $itemIdList)) {
throw new \RuntimeException("Parameters fault",16);
}
$itemIdList[] = $itemIdAndQuantity["itemId"];
}
} catch (\Throwable $e) {
var_dump($e);
die;
}
/** @var int[] $itemIdList */
$itemIdList = [];
//重现期望结果的开关
$showExpect = false;
if ($showExpect) {
//期望的正常结果 返回不同的数字
foreach ($itemIdAndQuantityList as &$itemIdAndQuantity) {
$itemIdList[] = $itemIdAndQuantity["itemId"];
}
} else {
//出现奇怪的结果 返回最后两个 数字变相同了
foreach ($itemIdAndQuantityList as $itemIdAndQuantity) {
$itemIdList[] = $itemIdAndQuantity["itemId"];
}
}
var_dump($itemIdList);
1
zjsxwc OP 补充:
期望结果($showExpect = true;)打印 ``` [4]=> int(10448) [5]=> int(10449) ``` 诡异结果($showExpect = false;)打印 ``` [4]=> int(10448) [5]=> int(10448) ``` |
2
zjsxwc OP 猜到原因了,
foreach 第一次的时候会 对`$itemIdAndQuantity`赋值, 此时`$itemIdAndQuantity`仍旧是对最后一个元素的引用,于是最后一个元素被覆盖成第一个值了,赋值之后`$itemIdAndQuantity`就不在是个引用了,执行正常逻辑。 解决办法就是要么全用 `&$itemIdAndQuantity` ,要么在每次 foreach 之后 unset 掉那个引用。 |
3
z5864703 2020-03-06 15:43:22 +08:00
你可以在$showExpect = false 之前 dump 下$itemIdAndQuantityList 的值就知道了。
最后一个键是引用值 |
4
Airon 2020-03-06 15:54:43 +08:00
引用的问题,要么都用&,要么 unset 掉,要么用不一样的命名
|
5
skymei 2020-03-06 16:13:52 +08:00
```PHP
$data = [1, 2, 3, 4]; $datum = &$data[3]; foreach ($data as $datum) { xdebug_debug_zval('data'); } |
6
skymei 2020-03-06 16:41:50 +08:00 1
```PHP
$data = [1, 2, 3, 4]; $datum = &$data[3]; foreach ($data as $datum) { xdebug_debug_zval('data'); } ``` 代码简化如上: 1.$datum 指向数组的最后一个元素地址和值 4 2.$datum 被赋予数组第一个元素值,由于是引用,因此将数组的第四个元素值改为了第一个元素值 1, 地址引用仍指向最后一个元素 [1, 2, 3, 1] 3.$datum 被赋予数组第二个元素值,由于是引用,因此将数组的第四个元素值改为了第二个元素值 2, 地址引用仍指向最后一个元素 [1, 2, 3 ,2] 4.$datum 被赋予数组第三个元素值,由于是引用,因此将数组的第四个元素值改为了第三个元素值 3, 地址引用仍指向最后一个元素 [1, 2, 3 ,3] 4.$datum 被赋予数组第四个元素值,由于是引用,因此将数组的第四个元素值改为了第四个元素值 3, 地址引用仍指向最后一个元素 [1, 2, 3 ,3] |
7
Achiii 2020-03-06 16:45:55 +08:00
我猜你用了引用,引用之后第二个循环会丢掉最后一个元素。别问我怎么知道的
|
8
pinews 2020-03-06 19:15:58 +08:00
建议新建一个数组。
|