Подтвердить что ты не робот

Mysqli_fetch_assoc() ожидает параметр/вызов функции-члена bind_param() ошибки. Как получить ошибку MySQL и исправить ее?

В моей локальной среде/среде разработки MySQLi-запрос выполняется нормально. Тем не менее, когда я загружаю его в моей среде веб-хостинга, я получаю эту ошибку:

Неустранимая ошибка: вызов функции-члена bind_param() для необъекта в...

Вот код:

global $mysqli;
$stmt = $mysqli->prepare("SELECT id, description FROM tbl_page_answer_category WHERE cur_own_id = ?");
$stmt->bind_param('i', $cur_id);
$stmt->execute();
$stmt->bind_result($uid, $desc);

Чтобы проверить свой запрос, я попытался выполнить запрос через панель управления phpMyAdmin, и результат в порядке.

4b9b3361

Ответ 1

Иногда ваш код mysqli выдает ошибку типа mysqli_fetch_assoc() expects parameter, Call to a member function bind_param() или аналогичную. Или даже без каких-либо ошибок, но запрос все равно не работает. Это означает, что ваш запрос не был выполнен.

Каждый раз при сбое запроса MySQL выдает сообщение об ошибке, объясняющее причину. К сожалению, по умолчанию такие ошибки не передаются в PHP, и все, что у вас есть, - это загадочное сообщение об ошибке, упомянутое выше. Следовательно, очень важно настроить PHP и mysqli, чтобы сообщать вам об ошибках MySQL. И как только вы получите сообщение об ошибке, решение проблемы будет несложным.

Как получить сообщение об ошибке в MySQL

Прежде всего, всегда используйте эту строку, прежде чем mysqli подключится во всех ваших средах:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

После этого все ошибки MySQL будут переведены в исключения PHP. Необработанное исключение, в свою очередь, приводит к фатальной ошибке в PHP. Таким образом, в случае ошибки MySQL вы получите обычную ошибку PHP. Это немедленно сообщит вам о причине ошибки. А трассировка стека приведет вас к точному месту, где произошла ошибка.

Как настроить PHP в разных средах

Вот суть моей статьи о сообщениях об ошибках PHP:
Сообщения об ошибках в разработке и на работающем сервере должны отличаться. На dev-сервере удобно отображать ошибки на экране, но на реальном сервере сообщения об ошибках должны регистрироваться вместо этого, чтобы вы могли найти их в журнале ошибок сервера.

Вы должны установить соответствующие параметры конфигурации для следующих значений

  • На сервере разработки

    • error_reporting должно быть установлено в значение E_ALL;
    • log_errors должен быть установлен в 1 (удобно иметь журналы на ПК разработчика)
    • display_errors должно быть установлено на 1
  • На рабочем сервере

    • error_reporting должно быть установлено в значение E_ALL;
    • log_errors должен быть установлен в 1
    • display_errors должен быть установлен в 0

Как на самом деле использовать это?

Просто удалите любой код, который проверяет на наличие ошибок вручную, все эти or die(), if ($result) и тому подобное. Просто напишите свой код взаимодействия с базой данных сразу:

$stmt = $this->con->prepare("INSERT INTO table(name, quantity) VALUES (?,?)");
$stmt->bind_param("si", $name, $quantity);
$stmt->execute();

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

Что делать с сообщением об ошибке, которое вы получаете

Получив сообщение об ошибке, вы должны прочитать и понять его. Это звучит слишком очевидно, но ученики часто упускают из виду крайнюю полезность сообщения об ошибке. Тем не менее, в большинстве случаев это объясняет проблему довольно просто. Скажем, если он говорит, что конкретной таблицы не существует, вы должны проверить орфографию, опечатки, регистр букв, учетные данные и тому подобное. Или, если он говорит, что в синтаксисе SQL есть ошибка, то вам нужно проверить ваш SQL. И проблемное место находится прямо перед тем, как часть запроса процитирована в сообщении об ошибке.

Если вы не понимаете сообщение об ошибке, попробуйте Google его. И просматривая результаты, придерживайтесь ответов, которые объясняют ошибку, а не прямо дают решение. Решение может не сработать в вашем конкретном случае, но объяснение поможет вам понять проблему и даст вам возможность решить ее самостоятельно.

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

Список того, что вы никогда не должны делать в отношении сообщений об ошибках

  • Никогда не используйте оператор подавления ошибок (@)! Это делает программиста неспособным прочитать сообщение об ошибке и, следовательно, не может исправить ошибку
  • Не используйте die() или echo или любую другую функцию для безоговорочной печати сообщения об ошибке на экране. PHP сообщит об этом сам и сделает все правильно, в зависимости от среды.
  • Не добавляйте условие для проверки результата запроса вручную (например, if($result)). Либо ваш запрос не удался, и вы уже получите исключение ошибки, либо все было в порядке, и проверять нечего.
  • Не используйте оператор try..catch для отображения сообщения об ошибке. Этот оператор должен использоваться для выполнения некоторой обработки ошибок, таких как откат транзакции. Но никогда не используйте его только для сообщения об ошибках - как мы узнали выше, PHP уже может сделать это правильным способом.

P.S.
Иногда нет ошибок, но нет и результатов. Тогда это означает, что в базе данных нет данных, соответствующих вашим критериям. В этом случае вы должны признать этот факт. Даже если вы можете поклясться данными и с критериями все в порядке. Они не. Вы должны проверить их снова. У меня есть статья, которая может помочь в этом вопросе, Как отлаживать взаимодействие с базой данных. Хотя это написано для PDO, но принцип тот же. Просто следуйте этой инструкции шаг за шагом и либо решите свою проблему, либо ответьте на вопрос Кару.

Ответ 2

@wulfnb Здравствуйте, в вашем коде обновления вы пропускаете имя файла условия условия для запроса на обновление.

Ответ для: запрос на обновление не обновляется в объектно-ориентированном php mysqli

→ Это твой код

    function update_password()
{
    $start = microtime(true);
    $conn = new mysqli('localhost', 'root', '123456', 'mydb');

if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

    $sql = "SELECT id, password FROM user WHERE new_password IS NULL LIMIT 1000;";

    $pass_array = $conn->query($sql);

    if ($pass_array->num_rows == 0) {
        $time_elapsed_secs = microtime(true) - $start;
        echo "Found like its finished processing";
        echo $time_elapsed_secs;
        return true;
    } else {
        while ($row = $pass_array->fetch_assoc()) {
            $a1 = new MyCypher2();
            $pass = $a1->decryptData($row['password']);
            $a2 = new MyCypher();
            $pass_ennew = $a2->encrypt($pass);
            $sql2 = "UPDATE 'user' SET 'password' = '".$pass_ennew. "', 'new_password' = 1 WHERE = ".$row['id'].";";
            $conn->query($sql2);
        }
    }

    $conn->close();
}

@wulfnb, пожалуйста, смотрите обновленный код здесь:

    function update_password()
{
    $start = microtime(true);
    $conn = new mysqli('localhost', 'root', '123456', 'mydb');

    if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
    }

        $sql = "SELECT id, password FROM user WHERE new_password IS NULL LIMIT 1000;";

        $pass_array = $conn->query($sql);

        if ($pass_array->num_rows == 0) {
            $time_elapsed_secs = microtime(true) - $start;
            echo "Found like its finished processing";
            echo $time_elapsed_secs;
            return true;
        } else {
            while ($row = $pass_array->fetch_assoc()) {
                $a1 = new MyCypher2();
                $pass = $a1->decryptData($row['password']);
                $a2 = new MyCypher();
                $pass_ennew = $a2->encrypt($pass);
                $sql2 = "UPDATE 'user' SET 'password' = '".$pass_ennew. "', 'new_password' = 1 WHERE 'id' = ".$row['id'].";";
                $conn->query($sql2);
            }
        }

    $conn->close();
}