我有一个多年前编写的 PHP 5 的 mysqli 包装器,但在尝试在 PHP 8.2.5 上运行时出现错误。我已经尝试了一切。以下是两个主要功能:
global $db_obj, $db_driver;
function db_login() {
global $db_obj;
$res = @$db_obj->connect(DB_HOST, DB_USER, DB_PASS);
if($res == false) {
display_error("Could not connect to database.");
}
db_maybe_handle_error();
db_select_db();
db_set_charset();
}
function db_select_db($db = DB_NAME) {
global $db_obj;
@$db_obj->select_db($db);
db_maybe_handle_error();
}
function db_set_charset($charset = 'utf8') {
global $db_obj;
@$db_obj->set_charset($charset);
db_maybe_handle_error();
}
function db_error() {
global $db_obj;
return $db_obj->error();
}
function db_maybe_handle_error($r = null, $extra_info = "") {
$e = db_error();
if($e != '') {
echo "mysql error: " . $e . " " . hsc($extra_info);
}
return $r;
}
function db_query($q) {
$num_args = func_num_args();
$arg_list = func_get_args();
$r = null;
global $db_obj;
if($num_args > 1) {
$stmt = $db_obj->stmt_init();
if($stmt->prepare($q)) {
$types = "";
$refArr = array("");
for($i = 1; $i < $num_args; $i++) {
$type = gettype($arg_list[$i]) === "integer" ? "i" : "s";
//$stmt->bind_param($type, $arg_list[$i]);
// PHP <=5.2: Remove the ampersand
// See http://php.net/manual/de/mysqli-stmt.bind-param.php
$refArr[] = &$arg_list[$i];
$types .= $type;
}
$refArr[0] = $types;
$ref = new ReflectionClass('mysqli_stmt');
$method = $ref->getMethod("bind_param");
$method->invokeArgs($stmt, $refArr);
$stmt->execute();
$stmt->store_result();
$r = $stmt;
} else {
db_maybe_handle_error(null, $q);
}
} else {
$r = @$db_obj->query($q);
}
db_maybe_handle_error(null, $q);
return $r;
}
function db_fetch($res, $use_numerical_indices = null) {
global $db_obj;
$use_numerical_indices = $use_numerical_indices === true ||
($use_numerical_indices === null && DB_DEFAULT_USE_NUMERICAL_INDEXES);
if(is_array($res)) {
return array_shift($res);
}
if($res instanceof mysqli_stmt) {
$res->store_result();
//$res->get_result();
$variables = array();
$data = array();
$meta = $res->result_metadata();
while($field = $meta->fetch_field()) {
$variables[] = &$data[$field->name];
}
call_user_func_array(array($res, 'bind_result'), $variables);
if(!$res->fetch()) {
$res->close();
return null;
}
$array = array();
$i = 0;
foreach($data as $k => $v) {
$array[$k] = $v;
if($use_numerical_indices) {
$array[$i] = $v;
}
$i++;
}
db_maybe_handle_error($array);
}
$result_type = $use_numerical_indices ? $db_obj->BOTH : $db_obj->ASSOC;
$r = @$db_obj->fetch_array($res, $result_type);
return db_maybe_handle_error($r);
}
function db_num_rows($res) {
global $db_obj;
if(is_array($res)) {
return count($res);
}
if($res instanceof mysqli_stmt) {
return mysqli_stmt_num_rows($res);
}
$r = @$db_obj->num_rows($res);
return db_maybe_handle_error($r);
}
function db_insert_id() {
global $db_obj;
$r = @$db_obj->insert_id();
return db_maybe_handle_error($r);
}
要获取一行,可以使用标准查询来完成:
$row = db_fetch(db_query("SELECT * FROM $table WHERE id=? LIMIT 1", $id));
带有 store_result() 的行(在 db_fetch 函数中)给出了此错误:
未捕获 mysqli_sql_Exception:命令不同步;您现在无法运行此命令
我已经尝试了几乎所有方法,包括尝试将 $stmt->free_result() 和 $stmt->close() 添加到代码的不同部分段。
问题是我特别请求帮助使用 $stmt->free_request() 或 $stmt->close() 重写此代码段,所以发生最少的代码更改并可以尽可能地保持原样。这些将在 db_query 和 db_fetch 函数中去哪里?
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
您收到的错误意味着您正在尝试无序执行 mysqli 函数(以及 MySQL 命令)。当 MySQL 收到此时不期望的命令时,它会回复此错误。
您不要在代码中的任何位置添加
free_result()或close()。正确结构的代码不应具有任何这些功能。它们只是为了防止意大利面条代码中的内存泄漏。要修复该错误,您必须确保操作以正确的顺序执行。但这段代码太混乱了,无法搞清它的情况。你必须重写它!
尝试像这样简单的事情:
function db_query($q, $params = []): mysqli_result { global $db_obj; // DO NOT USE GLOBALS!!! return $db_obj->execute_query($q, $params); } function db_fetch(mysqli_result $res, $use_numerical_indices = null) { $use_numerical_indices = $use_numerical_indices === true || ($use_numerical_indices === null && DB_DEFAULT_USE_NUMERICAL_INDEXES); $result_type = $use_numerical_indices ? MYSQLI_NUM : MYSQLI_ASSOC; return $res->fetch_array($result_type); }其他函数需要以类似的方式进行修剪。
实际问题是您调用了
store_result()两次。最简单的解决方法是删除其中之一。但是删除哪一个是一个谜,因为这段代码并没有明确说明哪一个(如果有的话)实际上是必要的。您可能可以删除两者,但是db_num_rows将不起作用。