Имея этот код:

 $sql = "SELECT * FROM users WHERE user_login=?;";
        $stmt = mysqli_stmt_init($conn);

        if (!mysqli_stmt_prepare($stmt, $sql)) {
            die(mysqli_error($conn));
        } else {
            mysqli_stmt_bind_param($stmt, 's', $login);
            mysqli_stmt_execute($stmt);
            mysqli_store_result($conn);

            $resultCheck = mysqli_stmt_num_rows($stmt);

            //err == login name is already taken
            if ($resultCheck > 0) {
                die("login is taken");
            } else {
                $sql = "INSERT INTO users(user_login, user_email, user_pwd) VALUES (?, ?, ?);";
                $stmt = mysqli_stmt_init($conn);
                if (!mysqli_stmt_prepare($stmt, $sql)) {
                    die(mysqli_error($conn));
                } else {
                    $hashedPwd = password_hash($pwd, PASSWORD_DEFAULT);
                    mysqli_stmt_bind_param($stmt, 'sss', $login, $email, $hashedPwd);
                    mysqli_stmt_execute($stmt);
                }
                // insert_usertodb($conn, $login, $email, $pwd);
            }
        }

Работает нормально (например, часть, в которую вставлен пользователь, не дает никаких ошибок mysqli), однако, если я попытался использовать функцию, в которую вставлен пользователь:

function insert_usertodb($conn, $user_login, $user_email, $user_pwd)
{
    $sql = "INSERT INTO users(user_login, user_email, user_pwd) VALUES (?, ?, ?);";
    $stmt = mysqli_stmt_init($conn);
    if (!mysqli_stmt_prepare($stmt, $sql)) { // <-- this is where the error happens
        // err_signup('sqlierror', '', '');
        die('sqlierror: ' . mysqli_error($conn));
    } else {
        //hash password
        $hashedPwd = password_hash($user_pwd, PASSWORD_DEFAULT);
        mysqli_stmt_bind_param($stmt, 'sss', $user_login, $user_email, $hashedPwd);
        mysqli_stmt_execute($stmt);
        // header("Location: ../signup.php?signup=success");
    }
}

И используйте его вместо той части, куда вставлен пользователь (после ветки else -> функция закомментирована в конце), mysqli выдаст ошибку:

 Commands out of sync; you can't run this command now

Есть ли причина, по которой функция с идентичным кодом (например, буквально скопировала часть (где находится вставка) и просто изменила имя переменных на аргумент этой функции) генерирует ошибку рассинхронизации? а код без функции не работает?

0
milanHrabos 12 Фев 2021 в 23:32

1 ответ

Лучший ответ

Это потому, что вы использовали здесь неправильную функцию mysqli_store_result($conn);. Вместо этого вам следовало использовать mysqli_stmt_store_result($stmt);. Это означает, что ваш код работает не так, как вы хотели, и проверка на существование нарушена. Вот почему использовать mysqli_stmt_num_rows() - ужасная идея.

Причина, по которой он работает, когда его нет в функции, заключается в том, что вы вызываете деструктор для объекта $stmt, когда назначаете ему другое значение в $stmt = mysqli_stmt_init($conn);. Когда вызывается деструктор, он извлекает все результаты в фоновом режиме, чтобы «очистить» провод.

Если еще не поздно, подумайте об использовании PDO. Это проще, и вы не будете так часто совершать такие ошибки. Код, который вы написали с помощью mysqli, слишком многословен. Вам не нужна большая часть этого. С PDO это было бы намного проще.

0
Dharman 12 Фев 2021 в 20:51