我有一个多年前编写的 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
函数中去哪里?
P粉7181655402024-01-17 12:42:35
您收到的错误意味着您正在尝试无序执行 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
将不起作用。