
本文详解如何在 php 中安全、规范地将 mysql 查询结果(如用户订单明细)动态嵌入 html 表格,特别适用于邮件正文生成场景;重点解决循环嵌套位置错误、html 结构语义混乱、xss 风险及变量拼接逻辑断裂等常见问题。
本文详解如何在 php 中安全、规范地将 mysql 查询结果(如用户订单明细)动态嵌入 html 表格,特别适用于邮件正文生成场景;重点解决循环嵌套位置错误、html 结构语义混乱、xss 风险及变量拼接逻辑断裂等常见问题。
在构建订单邮件通知系统时,一个典型需求是:将单个用户的多条订单项(item、quantity、price、subtotal)动态填充至 HTML 表格的 区域,并整体嵌入 $emailbody 字符串变量中发送。但原始代码中存在两个关键缺陷:一是将 ✅ 正确解法:分离逻辑层与视图层,先收集数据,再结构化拼接 不要试图在双引号字符串中“写 PHP 循环”,而应采用以下三步模式: 以下是修复后的完整、可运行示例(已适配您的 invoicebtn 场景): 立即学习“PHP免费学习笔记(深入)”; ? 关键注意事项与最佳实践: 通过以上重构,您将获得一个语义正确、样式可控、安全可靠且易于调试的动态订单表格生成方案——不仅适用于邮件,亦可无缝复用于后台管理页或 PDF 导出模块。 循环体直接写在纯字符串 $emailbody 内部(PHP 无法解析其中的 while 或 foreach),二是未对数据库输出做转义,存在 XSS 和 HTML 结构破坏风险。
<?php
include "db.php";
if (isset($_POST['invoicebtn'])) {
$invoice = $_POST['invoice'];
// ① 获取用户基本信息(防 SQL 注入:建议改用预处理语句)
$stmt1 = $con->prepare("SELECT name, email, phone, address, orderTotal FROM users WHERE invoice = ?");
$stmt1->bind_param("s", $invoice);
$stmt1->execute();
$user = $stmt1->get_result()->fetch_assoc();
if (!$user) {
die("未找到对应发票号的用户信息");
}
$name = htmlspecialchars($user['name'], ENT_QUOTES, 'UTF-8');
$email = htmlspecialchars($user['email'], ENT_QUOTES, 'UTF-8');
$phone = htmlspecialchars($user['phone'], ENT_QUOTES, 'UTF-8');
$address = htmlspecialchars($user['address'], ENT_QUOTES, 'UTF-8');
$carttotal = (float)$user['orderTotal'];
// ② 获取该用户的全部订单项(同样建议预处理)
$stmt2 = $con->prepare("SELECT item, quantity, price, subtotal FROM orders WHERE invoice = ?");
$stmt2->bind_param("s", $invoice);
$stmt2->execute();
$orders = $stmt2->get_result()->fetch_all(MYSQLI_ASSOC);
// ③ 动态生成订单行 HTML(关键:在 PHP 逻辑区完成,而非字符串内)
$orderRows = '';
foreach ($orders as $row) {
$item = htmlspecialchars($row['item'], ENT_QUOTES, 'UTF-8');
$qty = (int)$row['quantity'];
$price = number_format((float)$row['price'], 2, '.', '');
$subtotal = number_format((float)$row['subtotal'], 2, '.', '');
$orderRows .= "<tr>
<td style='border: 1px solid #ddd; padding: 8px;'>{$item}</td>
<td style='border: 1px solid #ddd; padding: 8px; text-align:center;'>{$qty}</td>
<td style='border: 1px solid #ddd; padding: 8px; text-align:right;'>KES {$price}</td>
<td style='border: 1px solid #ddd; padding: 8px; text-align:right;'>KES {$subtotal}</td>
</tr>";
}
// ④ 组装最终 emailbody(纯字符串拼接,无 PHP 语法嵌入)
$date = date('d-m-Y H:i:s'); // 使用 24 小时制更专业
$emailbody = <<<EOD
<table style="margin:10px auto; border-collapse: collapse; border: 1px solid #000; font-family: Arial, sans-serif;">
<tr>
<th colspan="4" style="border: 1px solid #000; padding: 10px; background-color: #000; color: white; font-weight:600;">
<h4 style="margin:0;">Invoice Order No. # {$invoice}</h4>
</th>
</tr>
<tr>
<td colspan="4" style="text-align:left; border: 1px solid #ddd; padding: 12px;">
<p style="margin:4px 0; text-align:right;"><strong>{$name}</strong></p>
<p style="margin:4px 0; text-align:right;">{$address}</p>
<p style="margin:4px 0; text-align:right;">{$phone}</p>
<p style="margin:4px 0; text-align:right;">{$email}</p>
<p style="margin:4px 0; text-align:left;">Invoice Date: {$date}</p>
</td>
</tr>
<tr style="background-color: #333; color: white; font-weight:600;">
<th style="border: 1px solid #ddd; padding: 10px; text-align:left;">ITEM</th>
<th style="border: 1px solid #ddd; padding: 10px; text-align:center;">QUANTITY</th>
<th style="border: 1px solid #ddd; padding: 10px; text-align:right;">PRICE (KES)</th>
<th style="border: 1px solid #ddd; padding: 10px; text-align:right;">TOTAL (KES)</th>
</tr>
<!-- 订单明细行由 PHP 动态注入 -->
{$orderRows}
<tr>
<td colspan="4" style="background-color:#0a0512; color:white; text-align: right; padding:12px 25px; font-weight:bold;">
<strong>Total: KES " . number_format($carttotal, 2, '.', '') . "</strong>
</td>
</tr>
</table>
EOD;
} else {
header("Location:orders.php?Anauthorized=true");
exit;
}
?>
<!-- 输出预览(仅用于调试) -->
<!DOCTYPE html>
<html>
<head><title>Invoice Preview</title></head>
<body>
<?php echo $emailbody; ?>
</body>
</html>



















