我有一個多年前寫的 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
函數中去哪裡?
您收到的錯誤表示您正在嘗試無序執行 mysqli 函數(以及 MySQL 指令)。當 MySQL 收到此時不期望的命令時,它會回覆此錯誤。
您不要在程式碼中的任何位置新增
free_result()
或close()
。正確結構的程式碼不應具有任何這些功能。它們只是為了防止意大利麵條代碼中的內存洩漏。要修復該錯誤,您必須確保操作以正確的順序執行。但這段程式碼太混亂了,無法搞清它的情況。你必須重寫它!
嘗試這樣簡單的事情:
其他函數需要以類似的方式進行修剪。
實際問題是您呼叫了
store_result()
兩次。最簡單的解決方法是刪除其中一個。但是刪除哪一個是一個謎,因為這段程式碼並沒有明確說明哪一個(如果有的話)實際上是必要的。您可能可以刪除兩者,但是db_num_rows
將無法運作。