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

PHP创建表格行前校验值 解决服务时长价格表列错位问题

问题根源

你现有代码存在两个直接导致渲染异常的问题:

  • 原始数据中同一款服务的不同时长价格被拆分为多条独立记录,直接遍历每条记录生成一行表格,会导致同个服务重复生成多行。
  • 生成单元格时仅在匹配到对应时长时才输出<td>标签,未匹配的位置不输出空单元格占位,HTML表格会自动将后续单元格向前补位,直接导致所有价格错位到第一列。
修复方案

核心逻辑分两步:先按服务维度聚合数据,再严格按表头顺序生成单元格,无对应价格时输出空单元格保证列对齐,值校验逻辑直接嵌入单元格生成环节即可。

修复后完整代码

// 预定义所有时长档位,固定顺序保证列对齐
$allSlots = ["45min", "1h", "1,5h", "2h", "2,5h", "3h"];
$groupedServices = [];
$existSlots = [];

// 第一步:按服务ID聚合同服务的所有时长价格,同时统计实际存在的时长列
foreach ($tableRow as $item) {
    $serviceId = $item['id'];
    if (!isset($groupedServices[$serviceId])) {
        $groupedServices[$serviceId] = [
            'name' => $item['name'],
            'prices' => []
        ];
    }
    $groupedServices[$serviceId]['prices'][$item['slot']] = $item['price'];
    if (!in_array($item['slot'], $existSlots)) {
        $existSlots[] = $item['slot'];
    }
}

// 第二步:生成表格头部,仅展示实际存在价格的时长列
$table = '<div class="product-table-wrap product-table-responsive">
    <table class="product-table">
        <thead class="product-table-head">
            <tr class="product-table-row">
                <th class="product-table-cell category-title"><span class="product-pricing-text">'.$cat_name.'</span></th>';
foreach ($allSlots as $slot) {
    if (in_array($slot, $existSlots)) {
        $table .= '<th class="product-table-cell product-duration"><span class="product-pricing-text">'.$slot.'</span></th>';
    }
}
$table .= '</tr>
        </thead>
        <tbody class="product-table-body">';

// 第三步:逐行生成服务数据,按表头顺序输出单元格
foreach ($groupedServices as $service) {
    $table .= '<tr>';
    $table .= '<td class="product-table-cell category-title"><span class="product-pricing-text">'.$service['name'].'</span></td>';
    foreach ($allSlots as $slot) {
        // 跳过表头不存在的列
        if (!in_array($slot, $existSlots)) continue;
        
        if (isset($service['prices'][$slot])) {
            $rawPrice = trim($service['prices'][$slot]);
            // ---------------值校验逻辑开始---------------
            $validPrice = '';
            // 校验1:空值直接跳过
            if (empty($rawPrice)) {
                $validPrice = '';
            }
            // 校验2:匹配金额格式(支持数字、小数点/逗号分隔、可选欧元符号)
            elseif (preg_match('/^\d+([.,]\d{1,2})?€?$/', $rawPrice)) {
                // 转义特殊字符防XSS
                $validPrice = htmlspecialchars($rawPrice, ENT_QUOTES);
            }
            // 校验不通过时显示占位符
            else {
                $validPrice = '-';
            }
            // ---------------值校验逻辑结束---------------
            $table .= '<td class="product-table-cell product-duration"><a href="#" class="product-pricing-text">'.$validPrice.'</a></td>';
        } else {
            // 无对应价格输出空单元格占位,保证列不错位
            $table .= '<td class="product-table-cell product-duration"></td>';
        }
    }
    $table .= '</tr>';
}

// 原有固定的泰式按摩行,按列数自动适配
$table .= '<tr class="product-table-row">
    <td class="product-table-cell category-title"><span class="product-pricing-text">Thai massage</span></td>';
$fixedPriceMap = [
    '45min' => '48,00',
    '1h' => '66,00',
    '1,5h' => '78,00',
    '2h' => '93,00',
    '2,5h' => '108,00'
];
foreach ($allSlots as $slot) {
    if (!in_array($slot, $existSlots)) continue;
    $price = $fixedPriceMap[$slot] ?? '';
    $tag = $slot === '45min' ? '<a href="#"' : '<span';
    $closeTag = $slot === '45min' ? '</a>' : '</span>';
    $table .= '<td class="product-table-cell product-duration">'.$tag.' class="product-pricing-text">'.$price.$closeTag.'</td>';
}

$table .= '</tr>
        </tbody>
    </table>
</div>';

echo $table;

校验规则说明

你可以根据自己的业务需求调整校验逻辑:

  • 价格格式校验:修改正则规则适配你的货币单位、小数位数要求
  • 空值处理:可以设置默认显示文本,也可以留空
  • 特殊字符转义:必须保留htmlspecialchars()处理,避免用户输入恶意脚本导致XSS漏洞
  • 异常值处理:校验不通过的价格可以显示-或者添加错误样式,方便后台排查数据问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:33:35