为PDF报表生成不同长度表格的PHP代码优化咨询
报表功能PHP代码优化方案
当前报表代码可正常运行,以下从数据处理逻辑、Helper函数、调用逻辑三个维度优化,提升可维护性与复用性:
一、数据处理逻辑优化
核心问题:重复正则处理、冗余循环、硬编码阈值
原代码中多次调用preg_replace处理code_value,且用原生循环拆分数据,可通过Laravel集合方法简化,同时提取阈值常量避免硬编码。
优化后代码:
// 提取阈值常量,便于统一修改 define('REPORT_THRESHOLDS', [ 'none_reactive' => 0.35, 'low_upper' => 3.49, 'medium_lower' => 3.5, 'medium_upper' => 49.99, 'high_lower' => 50.0, ]); // 封装数据处理逻辑到Service类(推荐) class ReportDataProcessor { public static function process($rawData, $foodSense) { $processedData = collect($rawData) ->sortBy('cate_id') ->map(function ($item) { // 只处理一次code_value,避免重复正则 $cleanCodeValue = (float)preg_replace('#[^\w()/.%\-&]#', '', $item->code_value); return [ 'name' => $item->name, 'ar_name' => $item->ar_name, 'code_value' => $item->code_value, 'clean_code_value' => $cleanCodeValue, // 新增处理后数值,供后续判断 'code' => $item->code, 'cate_id' => $item->cate_id, 'cat_name' => $item->cat_name, ]; }) ->values(); // 重置索引,避免集合键混乱 // 用集合filter拆分数据,替代原生循环 $higherValueData = $processedData->filter(fn($item) => $item['clean_code_value'] > REPORT_THRESHOLDS['none_reactive'])->values()->all(); $lowerValueData = $processedData->filter(fn($item) => $item['clean_code_value'] <= REPORT_THRESHOLDS['none_reactive'])->values()->all(); $totalValues = $processedData->all(); return [ 'lowCount' => self::countLow($processedData), 'highCount' => self::countHigh($processedData), 'foodSense' => $foodSense, 'reportData' => $processedData, 'mediumCount' => self::countMedium($processedData), 'lowerValueData' => $lowerValueData, 'higherValueData' => $higherValueData, 'noneReactiveCount' => self::countNoneReactive($processedData), 'totalValues' => $totalValues ]; } // 拆分统计逻辑为独立方法,便于复用和测试 private static function countNoneReactive($data) { return $data->filter(fn($item) => $item['clean_code_value'] <= REPORT_THRESHOLDS['none_reactive'])->count(); } private static function countLow($data) { return $data->filter(fn($item) => $item['clean_code_value'] > REPORT_THRESHOLDS['none_reactive'] && $item['clean_code_value'] <= REPORT_THRESHOLDS['low_upper'] )->count(); } private static function countMedium($data) { return $data->filter(fn($item) => $item['clean_code_value'] >= REPORT_THRESHOLDS['medium_lower'] && $item['clean_code_value'] <= REPORT_THRESHOLDS['medium_upper'] )->count(); } private static function countHigh($data) { return $data->filter(fn($item) => $item['clean_code_value'] >= REPORT_THRESHOLDS['high_lower'])->count(); } } // 调用示例 $data = ReportDataProcessor::process($rawData, $foodSense);
优化点:
- 仅处理一次
code_value,提升性能 - 用Laravel集合替代原生循环/数组操作,代码更简洁
- 阈值集中管理,修改无需多处改动
- 统计逻辑拆分为独立方法,便于单元测试和复用
二、display_table Helper函数优化
核心问题:HTML拼接易出错、逻辑混乱、无XSS防护、参数冗余
原函数用字符串拼接HTML,逻辑绕且无转义,可拆分逻辑、添加XSS防护、优化参数传递。
优化后代码:
if (!function_exists('display_table')) { function display_table(array $options) { $start = $options['start'] ?? 0; $end = $options['end'] ?? count($options['tableValue']); $tableValue = $options['tableValue']; $currentNumber = $options['number'] ?? 1; $currentCategory = null; // 截取需处理的数据子集 $subset = array_slice($tableValue, $start, $end - $start); $html = '<table class="sensitivity-data-table"><tbody>'; foreach ($subset as $item) { // 输出分类表头(仅当分类变化时) if ($currentCategory !== $item['cate_id']) { $html .= sprintf( '<tr><th class="th-lg" colspan="2">%s</th><th class="th-sm sensitivity-tab">Sensitivity</th></tr>', htmlspecialchars($item['cat_name']) // XSS防护 ); $currentCategory = $item['cate_id']; } // 输出数据行 $html .= sprintf( '<tr> <td class="td-lg" colspan="2">%d: %s-%s<span>%s</span></td> <td class="td-sm"><span class="sensitivity-circle %s"></span></td> </tr>', $currentNumber, htmlspecialchars($item['name']), htmlspecialchars($item['ar_name']), htmlspecialchars($item['code_value']), getColor($item['clean_code_value'] ?? $item['code_value']) // 优先用处理后的值 ); $currentNumber++; } $html .= '</tbody></table>'; // 返回清晰的键名,避免歧义 return [ 'next_number' => $currentNumber, 'html' => $html, 'processed_count' => count($subset) ]; } }
优化点:
- 用
sprintf替代字符串拼接,代码更易读且减少语法错误 - 添加
htmlspecialchars转义输出内容,防止XSS攻击 - 用数组参数替代多个独立参数,避免参数顺序混乱
- 逻辑拆分:先处理子集,再遍历生成行,可读性提升
- 返回键名更清晰(如
next_number替代start)
三、调用逻辑优化
核心问题:手动分页易出错、变量拼写错误($hightStart→$highStart)
原调用代码需手动维护start/end,可封装为自动分页函数,减少重复代码。
优化后代码:
// 封装分页生成表格逻辑 function generate_sensitivity_tables(array $data, $perPage = 20) { $total = count($data); $currentNumber = 1; $currentStart = 0; while ($currentStart < $total) { $currentEnd = min($currentStart + $perPage, $total); $result = display_table([ 'start' => $currentStart, 'end' => $currentEnd, 'tableValue' => $data, 'number' => $currentNumber ]); echo $result['html']; $currentStart = $currentEnd; $currentNumber = $result['next_number']; } } // 调用示例 generate_sensitivity_tables($data['higherValueData'], 20);
优化点:
- 自动处理分页逻辑,无需手动维护
start/end - 修复变量拼写错误,避免逻辑bug
- 封装后可在多处复用,减少重复代码
额外建议
- 视图层分离:如果使用Laravel,建议用Blade模板生成HTML表格,而非在Helper中拼接,比如创建
components/sensitivity-table.blade.php,将表格逻辑移至视图,更符合MVC架构。 - 单元测试:对
ReportDataProcessor中的统计方法、display_table函数编写单元测试,确保逻辑修改后不影响现有功能。 - 类型提示:PHP 7+支持类型提示,可给函数参数、返回值添加类型,提升代码可读性和IDE支持。
内容的提问来源于stack exchange,提问作者Shakeel Ahmad
相关产品推荐
相关产品推荐

