本文目录导读:

在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);
注意事项
- 安全性:始终使用参数绑定,避免SQL注入
- 参数匹配:确保传递给存储过程的参数数量和类型正确
- 连接状态:存储过程执行后可能占用连接,记得处理结果集
- 错误处理:使用try-catch捕获异常,提供友好的错误提示
通过这些方法,你可以在ThinkPHP项目中灵活地调用各种存储过程。