ThinkPHP项目存储过程调用

wen PHP项目 3

本文目录导读:

ThinkPHP项目存储过程调用

  1. 使用原生SQL查询
  2. 使用模型调用
  3. 使用参数绑定(更安全的写法)
  4. 处理存储过程的OUT参数
  5. 封装成通用方法
  6. 处理多个结果集
  7. 事务中的存储过程调用
  8. 参数类型指定
  9. 注意事项

在ThinkPHP中调用存储过程,主要有以下几种方式:

使用原生SQL查询

使用query()方法(返回结果集)

// 调用返回结果集的存储过程
$result = Db::query("CALL get_user_list(?)", [$userId]);
// 带多个参数
$result = Db::query("CALL get_user_info(?, ?)", [$userId, $status]);

使用execute()方法(不返回结果集)

// 执行不返回结果的存储过程
Db::execute("CALL update_user_status(?)", [$userId]);
// 带多个参数
Db::execute("CALL batch_update_users(?, ?)", [$startId, $endId]);

使用模型调用

// 在模型中定义方法
class User extends Model
{
    // 调用存储过程
    public static function callGetUserList($params)
    {
        return Db::query("CALL get_user_list(?)", $params);
    }
    // 调用存储过程并返回结果
    public static function callProcedure($procName, $params = [])
    {
        $placeholders = implode(',', array_fill(0, count($params), '?'));
        $sql = "CALL {$procName}({$placeholders})";
        return Db::query($sql, $params);
    }
}
// 调用方式
$userList = User::callGetUserList([$userId]);

使用参数绑定(更安全的写法)

// 使用命名绑定
$result = Db::query("CALL get_user_by_condition(:id, :status)", [
    ':id' => $userId,
    ':status' => 1
]);
// 或者使用PDO绑定
$pdo = Db::getPdo();
$stmt = $pdo->prepare("CALL get_user_list(?, ?)");
$stmt->bindValue(1, $userId, PDO::PARAM_INT);
$stmt->bindValue(2, $status, PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetchAll();

处理存储过程的OUT参数

// 使用PDO处理OUT参数
$pdo = Db::getPdo();
$stmt = $pdo->prepare("CALL get_user_count(?)");
$stmt->bindParam(1, $count, PDO::PARAM_INT, 11);
$stmt->execute();
echo "用户总数: " . $count;
// 多个OUT参数
$stmt = $pdo->prepare("CALL get_stats(?, ?)");
$stmt->bindParam(1, $totalUsers, PDO::PARAM_INT, 11);
$stmt->bindParam(2, $activeUsers, PDO::PARAM_INT, 11);
$stmt->execute();
echo "总用户: $totalUsers, 活跃用户: $activeUsers";

封装成通用方法

// 封装一个通用的存储过程调用方法
class ProcedureService
{
    /**
     * 调用存储过程
     * @param string $procedure 存储过程名称
     * @param array $params 参数数组
     * @param bool $returnResult 是否返回结果集
     * @return mixed
     */
    public static function call($procedure, $params = [], $returnResult = true)
    {
        // 构建参数占位符
        $placeholders = array_fill(0, count($params), '?');
        $sql = "CALL {$procedure}(".implode(',', $placeholders).")";
        if ($returnResult) {
            return Db::query($sql, $params);
        } else {
            return Db::execute($sql, $params);
        }
    }
    // 调用示例
    public function example()
    {
        // 返回结果集
        $list = ProcedureService::call('get_user_list', [1, 100]);
        // 不返回结果
        ProcedureService::call('update_user', [1, '张三'], false);
    }
}

处理多个结果集

// 当存储过程返回多个结果集时
$pdo = Db::getPdo();
$stmt = $pdo->prepare("CALL get_multi_results(?)");
$stmt->execute([$userId]);
// 获取第一个结果集
$firstResult = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 移动到下一个结果集
$stmt->nextRowset();
$secondResult = $stmt->fetchAll(PDO::FETCH_ASSOC);

事务中的存储过程调用

// 在事务中调用存储过程
Db::startTrans();
try {
    // 执行存储过程
    Db::execute("CALL update_user_balance(?, ?)", [$userId, -100]);
    Db::execute("CALL record_transaction(?, ?, ?)", [$userId, -100, '消费']);
    // 提交事务
    Db::commit();
} catch (\Exception $e) {
    // 回滚事务
    Db::rollback();
    throw $e;
}

参数类型指定

// 强制指定参数类型
$pdo = Db::getPdo();
$stmt = $pdo->prepare("CALL search_users(?, ?)");
// 绑定参数并指定类型
$stmt->bindValue(1, $keyword, PDO::PARAM_STR);
$stmt->bindValue(2, $pageSize, PDO::PARAM_INT);
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

注意事项

  1. 安全性:始终使用参数绑定,避免SQL注入
  2. 参数匹配:确保传递给存储过程的参数数量和类型正确
  3. 连接状态:存储过程执行后可能占用连接,记得处理结果集
  4. 错误处理:使用try-catch捕获异常,提供友好的错误提示

通过这些方法,你可以在ThinkPHP项目中灵活地调用各种存储过程。

抱歉,评论功能暂时关闭!