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

如何使用PHPMailer从数据库获取邮件模板并插入变量

问题分析与修复建议

嘿,我看了你这段代码,发现几个关键问题需要调整,咱们一步步来解决:

1. mysqli_multi_query 的结果处理完全错了

mysqli_multi_query执行后,返回的只是第一个查询的结果集,根本不能用foreach直接遍历所有三个查询的结果。你得手动依次获取每个结果集才行。

2. 存在严重的SQL注入风险

直接把用户提交的$bookid和$username拼进SQL语句里,相当于给攻击者开了后门,必须用预处理语句来避免这个问题,这是Web开发的基础安全要求。

3. 模板变量替换没做

你只是把模板内容直接赋值给了$mail->Body,但没把$title和$name替换到模板里的对应位置——比如你的模板里应该有像{{title}}或者{name}这类占位符,得把这些占位符换成实际的变量值才行。


修正后的完整代码示例

if(isset($_POST['issue'])) {
    $username = $_POST['studentname'];
    $bookid = $_POST['bookdetails'];

    // 1. 用预处理语句分别处理每个查询,彻底避免SQL注入
    // 获取邮件模板
    $stmt = mysqli_prepare($connection, "SELECT option_value FROM settings WHERE option_name = 'email_temp_issue';");
    mysqli_stmt_execute($stmt);
    $result = mysqli_stmt_get_result($stmt);
    $templateRow = mysqli_fetch_assoc($result);
    $email_template = $templateRow['option_value'] ?? ''; // 处理模板不存在的情况,避免报错
    mysqli_stmt_close($stmt);

    // 获取书籍标题(注意:如果bookid是整数,把bind_param的第二个参数改成"i")
    $stmt = mysqli_prepare($connection, "SELECT title FROM books WHERE id = ?;");
    mysqli_stmt_bind_param($stmt, "s", $bookid);
    mysqli_stmt_execute($stmt);
    $result = mysqli_stmt_get_result($stmt);
    $bookRow = mysqli_fetch_assoc($result);
    $title = $bookRow['title'] ?? '未知书籍';
    mysqli_stmt_close($stmt);

    // 获取学生姓名
    $stmt = mysqli_prepare($connection, "SELECT fullName from students WHERE email = ?;");
    mysqli_stmt_bind_param($stmt, "s", $username);
    mysqli_stmt_execute($stmt);
    $result = mysqli_stmt_get_result($stmt);
    $studentRow = mysqli_fetch_assoc($result);
    $name = $studentRow['fullName'] ?? '未知用户';
    mysqli_stmt_close($stmt);

    // 2. 替换模板中的占位符(这里假设模板里用{{title}}和{{name}}作为标记,你可以根据实际模板调整)
    $mailBody = str_replace(
        ['{{title}}', '{{name}}'],
        [$title, $name],
        $email_template
    );

    // 3. 把替换后的内容赋值给PHPMailer的Body
    $mail->Body = $mailBody;

    if(!$mail->Send()) {
        echo "<script>alert('Error while sending Email.')</script>";
        var_dump($mail);
    } else {
        echo "<script>alert('Email sent successfully')</script>";
    }
}

额外说明

  • 为什么不用multi_query? 虽然它能执行多个查询,但可读性差,而且处理结果集容易出错,分开处理每个查询更清晰,也更容易维护。
  • 如果一定要用multi_query(不推荐),正确的处理方式是这样的:
    $sql= "SELECT option_value FROM settings WHERE option_name = 'email_temp_issue';";
    $sql .="SELECT title FROM books WHERE id = ?;";
    $sql .="SELECT fullName from students WHERE email = ?";
    
    // 还是要用预处理绑定参数,不能直接拼变量
    $stmt = mysqli_prepare($connection, $sql);
    mysqli_stmt_bind_param($stmt, "ss", $bookid, $username);
    mysqli_stmt_execute($stmt);
    
    // 获取第一个结果集(邮件模板)
    $result = mysqli_stmt_get_result($stmt);
    $templateRow = mysqli_fetch_assoc($result);
    $email_template = $templateRow['option_value'] ?? '';
    
    // 切换到第二个结果集(书籍标题)
    mysqli_stmt_next_result($stmt);
    $result = mysqli_stmt_get_result($stmt);
    $bookRow = mysqli_fetch_assoc($result);
    $title = $bookRow['title'] ?? '未知书籍';
    
    // 切换到第三个结果集(学生姓名)
    mysqli_stmt_next_result($stmt);
    $result = mysqli_stmt_get_result($stmt);
    $studentRow = mysqli_fetch_assoc($result);
    $name = $studentRow['fullName'] ?? '未知用户';
    
    mysqli_stmt_close($stmt);
    
  • 模板占位符:如果你的模板里用的是其他标记(比如%title%或者{name}),记得修改str_replace里的搜索数组,匹配你的实际占位符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 08:22:47