"Mysqli_sql_exception non intercepté : la commande est désynchronisée ; vous ne pouvez pas exécuter cette commande maintenant" lors de la mise à jour vers php8.2.5 à partir d'une ancienne version de PHP
P粉883278265
P粉883278265 2024-01-16 14:25:42
0
1
515

J'ai un wrapper mysqli pour PHP 5 que j'ai écrit il y a des années, mais j'obtiens une erreur en essayant de l'exécuter sur PHP 8.2.5. J'ai tout essayé. Voici les deux fonctionnalités principales :

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);
}

Pour obtenir une ligne, cela peut être fait à l'aide d'une requête standard :

$row = db_fetch(db_query("SELECT * FROM $table WHERE id=? LIMIT 1", $id));

dans une fonction avec store_result() 的行(在 db_fetch) donne cette erreur :

Mysqli_sql_Exception non intercepté : commande désynchronisée ; vous ne pouvez pas exécuter cette commande maintenant

J'ai presque tout essayé, y compris essayer d'ajouter $stmt->free_result()$stmt->close() à différentes sections de code.

La question est que je demande spécifiquement de l'aide pour utiliser $stmt->free_request()$stmt->close() 重写此代码段,所以发生最少的代码更改并可以尽可能地保持原样。这些将在 db_querydb_fetchOù aller dans la fonction ?

P粉883278265
P粉883278265

répondre à tous(1)
P粉718165540

L'erreur que vous recevez signifie que vous essayez d'exécuter les fonctions mysqli (et donc les commandes MySQL) dans le désordre. MySQL répond avec cette erreur lorsqu'il reçoit une commande à laquelle il ne s'attend pas pour le moment.

Vous n'ajoutez free_result()close() nulle part dans votre code. Un code correctement structuré ne devrait avoir aucune de ces fonctionnalités. Ils servent simplement à éviter les fuites de mémoire dans le code Spaghetti.

Pour corriger cette erreur, vous devez vous assurer que les opérations sont effectuées dans le bon ordre. Mais ce code est trop confus pour comprendre ce qui se passe. Il faut le réécrire !

Essayez quelque chose de simple comme ceci :

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);
}

Les autres fonctions doivent être élaguées de la même manière.

Le vrai problème est que si vous appelez store_result() 两次。最简单的解决方法是删除其中之一。但是删除哪一个是一个谜,因为这段代码并没有明确说明哪一个(如果有的话)实际上是必要的。您可能可以删除两者,但是 db_num_rows ça ne marchera pas.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!