You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP7迁移至PHP8:each()函数替换后循环及行数异常问题

PHP7迁移PHP8:each()替换foreach后的问题修复

问题背景

将PHP7脚本迁移至PHP8时,原代码依赖已废弃的each()函数,两次替换为foreach后均出现异常:

  • 首次修改后触发无限循环
  • 二次修改后虽能运行,但原本3列多行的表格变为3列、行数为原3倍,且列值依次单独变动,不符合预期

原代码(PHP7环境)

do {
    $Tabelle->SetLine(array_values($Line));
    foreach($Line as $Spalte => $Kapitel) {
        list($Name, $URL) = each($URLs[$Spalte]);           
        if ($URL == "") $Line[$Spalte] = $Name; 
        else            $Line[$Spalte] = '<a href="'.$URL.'">'.$Name.'</a>';    
    }
} while (reset($Line) != "" || next($Line) != "" || next($Line) != "");

首次修改代码(出现无限循环)

do {
    $Tabelle->SetLine(array_values($Line));
    foreach($Line as $Spalte => $Kapitel) {
        foreach($URLs[$Spalte] as $Name => $URL)
            if ($URL == "") $Line[$Spalte] = $Name; 
            else            $Line[$Spalte] = '<a href="'.$URL.'">'.$Name.'</a>';    
    }
} while (reset($Line) != "" || next($Line) != "" || next($Line) != "");

二次修改代码(表格行数异常)

$Tabelle->SetLine(array_values($Line));
foreach($Line as $Spalte => $Kapitel) {
    foreach($URLs[$Spalte] as $Name => $URL) {
        if ($URL == "") $Line[$Spalte] = $Name; 
        else            $Line[$Spalte] = '<a href="'.$URL.'">'.$Name.'</a>';    
        $Tabelle->SetLine(array_values($Line));
    }
}

问题分析

  1. 首次修改的问题:
    内层foreach会遍历$URLs[$Spalte]的所有元素,最终$Line[$Spalte]会被赋值为该列URL数组的最后一个元素;外层do-while的判断条件永远为真(因为$Line始终被赋值为非空内容),导致无限循环。

  2. 二次修改的问题:
    将$Tabelle->SetLine()移至内层foreach后,每处理一个URL元素就添加一行表格,3列的URL数组各有n个元素时,会生成3n行;且每次仅修改一列的值,导致列值单独变动。

  3. 原代码逻辑:
    each()函数每次调用会返回数组的下一个元素并移动指针,原代码通过do-while循环,每次迭代为所有列分配当前指针位置的URL元素,直到所有列的指针都走到数组末尾,从而生成与URL数组行数匹配的表格行。

正确修改方案

模拟原each()的指针遍历逻辑,通过索引统一控制所有列的URL元素读取:

// 预存每个列URL数组的键列表
$urlColumnKeys = [];
foreach ($URLs as $spalte => $urlList) {
    $urlColumnKeys[$spalte] = array_keys($urlList);
}

$currentRowIndex = 0;
$hasValidData = true;

do {
    $hasValidData = false;
    foreach ($Line as $spalte => $_) {
        // 检查当前列是否存在对应索引的URL元素
        if (isset($urlColumnKeys[$spalte][$currentRowIndex])) {
            $hasValidData = true;
            $name = $urlColumnKeys[$spalte][$currentRowIndex];
            $url = $URLs[$spalte][$name];
            
            $Line[$spalte] = $url === "" 
                ? $name 
                : '<a href="'.$url.'">'.$name.'</a>';
        } else {
            // 无数据时设为空,确保循环能终止
            $Line[$spalte] = "";
        }
    }
    
    if ($hasValidData) {
        $Tabelle->SetLine(array_values($Line));
    }
    
    $currentRowIndex++;
} while ($hasValidData);

逻辑说明

  • 先收集每个列URL数组的键集合,避免每次循环重复计算
  • 通过统一的行索引$currentRowIndex,同步读取所有列的对应位置元素
  • 每次迭代生成完整的一行表格数据后,再调用SetLine()添加行
  • 当所有列都没有对应索引的元素时,终止循环,避免无限执行

内容的提问来源于stack exchange,提问作者Rscompu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 22:12:16