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

如何将调用存储过程的MySQLi PHP代码迁移至PDO?

把MySQLi存储过程调用迁移到PDO的完整方案

我来帮你把这些MySQLi调用存储过程的代码改成PDO版本,同时彻底摆脱手动转义的麻烦——PDO的预处理语句能完美替代mysqli_escape_string,更安全也更简洁。

第一步:重构数据库连接文件(conn.php)

原代码每次include都新建连接,PDO推荐复用连接,同时要设置正确的错误模式和字符集,避免乱码和调试困难:

<?php
// conn.php
$dsn = 'mysql:host=localhost;dbname=你的数据库名;charset=utf8mb4';
$username = '你的数据库用户名';
$password = '你的数据库密码';

try {
    $pdo = new PDO($dsn, $username, $password);
    // 设置错误模式为抛出异常,方便调试和捕获错误
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    // 默认返回关联数组,和mysqli_fetch_array(MYSQLI_ASSOC)行为一致
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch(PDOException $e) {
    die("数据库连接失败: " . $e->getMessage());
}
?>

第二步:重构function.php的存储过程调用函数

PDO用预处理语句替代手动转义,自动处理参数的安全问题。下面是改造后的每个函数:

<?php
// function.php
require_once("conn.php"); // 用require_once避免重复加载连接

function AddWords($word, $meaning, $synonym, $antonym) {
    global $pdo;
    // 用占位符替代手动拼接SQL,避免注入
    $stmt = $pdo->prepare("CALL AddWords(:word, :meaning, :synonym, :antonym)");
    // 直接传参数数组,PDO自动转义
    $stmt->execute([
        ':word' => $word,
        ':meaning' => $meaning,
        ':synonym' => $synonym,
        ':antonym' => $antonym
    ]);
    // 返回是否执行成功(影响行数大于0表示成功)
    return $stmt->rowCount() > 0;
}

function GetWords($word) {
    global $pdo;
    $stmt = $pdo->prepare("CALL GetWords(:word)");
    $stmt->execute([':word' => $word]);
    // 返回所有查询结果(关联数组格式)
    return $stmt->fetchAll();
}

function GetAdminWords() {
    global $pdo;
    // 无参数的存储过程可以直接用query
    $stmt = $pdo->query("CALL GetAdminWords()");
    return $stmt->fetchAll();
}

function GetWordsByID($id) {
    global $pdo;
    $stmt = $pdo->prepare("CALL GetWordsById(:id)");
    $stmt->execute([':id' => $id]);
    // 返回单条记录
    return $stmt->fetch();
}

function DeleteWords($id) {
    global $pdo;
    $stmt = $pdo->prepare("CALL DeleteWords(:id)");
    $stmt->execute([':id' => $id]);
    return $stmt->rowCount() > 0;
}

function UpdateWords($word, $meaning, $synonym, $antonym, $id) {
    global $pdo;
    $stmt = $pdo->prepare("CALL UpdateWords(:word, :meaning, :synonym, :antonym, :id)");
    $stmt->execute([
        ':word' => $word,
        ':meaning' => $meaning,
        ':synonym' => $synonym,
        ':antonym' => $antonym,
        ':id' => $id
    ]);
    return $stmt->rowCount() > 0;
}

function SortContent() {
    global $pdo;
    $stmt = $pdo->query("CALL SortContent()");
    return $stmt->fetchAll();
}

function SortContent2() {
    global $pdo;
    $stmt = $pdo->query("CALL SortContent2()");
    return $stmt->fetchAll();
}
?>

第三步:改造主调用文件的逻辑

去掉所有mysqli_escape_string调用,直接传递原始参数给PDO函数即可,同时调整结果处理的代码:

<?php
require_once("conn.php");
require_once("function.php");

// 处理表单提交
if(isset($_POST['btn_submit'])){
    $word = $_POST['word'];
    $meaning = $_POST['meaning'];
    $antonym = $_POST['antonym'];
    $synonym = $_POST['synonym'];

    if(!isset($_GET['id1'])){
        // 直接传参数,PDO自动处理转义
        $success = AddWords($word, $meaning, $synonym, $antonym);
        if($success){
            echo "<script type='text/javascript'>alert('Saved Successfully!!')</script>";
            echo "<script type='text/javascript'>window.location='view.php'</script>";
        } else {
            echo "<script type='text/javascript'>alert('Save failed!')</script>";
        }
    } else {
        $id = $_GET['id1'];
        $success = UpdateWords($word, $meaning, $synonym, $antonym, $id);
        if($success){
            echo "<script type='text/javascript'>alert('Saved Successfully!!')</script>";
            echo "<script type='text/javascript'>window.location='view.php'</script>";
        } else {
            echo "<script type='text/javascript'>alert('Update failed!')</script>";
        }
    }
}
?>

<?php
$word = $meaning = $synonym = $antonym = '';
if(isset($_GET['id1'])){
    $id = $_GET['id1'];
    // 获取单条记录,直接用PDO返回的关联数组
    $row = GetWordsByID($id);
    if($row){
        $word = $row['word'];
        $meaning = $row['meaning'];
        $synonym = $row['synonym'];
        $antonym = $row['antonym'];
    }
}
?>
<form method="post">
    <div class="container container-fluid">
        <div class="form-group">
            <div class="col-xs-4">
                <label for="inputdefault">Add Word</label>
                <input class="form-control" id="inputdefault" type="text" name="word" value="<?php echo htmlspecialchars($word); ?>">
                <label for="inputdefault">Add Meaning</label>
                <input class="form-control" id="inputdefault" type="text" name="meaning" value="<?php echo htmlspecialchars($meaning); ?>">
                <label for="inputdefault">Add Synonym</label>
                <input class="form-control" id="inputdefault" type="text" name="synonym" value="<?php echo htmlspecialchars($synonym); ?>">
                <label for="inputdefault">Add Antonym</label>
                <input class="form-control" id="inputdefault" type="text" name="antonym" value="<?php echo htmlspecialchars($antonym); ?>"><br>
                <button type="submit" class="btn btn-primary" name="btn_submit" >Submit</button>
            </div>
        </div>
    </div>
</form>

关键说明

  • 替代mysqli_escape_string:PDO的预处理语句会自动对参数进行转义,完全不需要手动调用转义函数,从根源上避免SQL注入。
  • 结果处理:PDO默认设置为关联数组,和原MySQLi的行为一致,迁移成本很低。
  • 错误处理:设置PDO::ERRMODE_EXCEPTION后,数据库错误会抛出异常,生产环境建议添加try-catch块来捕获和处理异常。
  • 连接复用:用require_once加载连接文件,避免重复创建数据库连接,提升性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:41:39