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

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

Я занят функцией, которая получает настройки из БД, и внезапно я столкнулся с этой ошибкой:

Fatal error: Call to a member function bind_param() on boolean in C:\xampp2\htdocs\application\classes\class.functions.php on line 16

Обычно это означает, что я выбираю материал из самых разных таблиц и прочее. Но в этом случае я не...

Здесь функция getSetting:

public function getSetting($setting)
{
    $query = $this->db->conn->prepare('SELECT value, param FROM ws_settings WHERE name = ?');
    $query->bind_param('s', $setting);
    $query->execute();
    $query->bind_result($value, $param);
    $query->store_result();
    if ($query->num_rows() > 0)
    {
        while ($query->fetch()) 
        {
            return $value;
            if ($param === '1')
            {
                $this->tpl->createParameter($setting, $value);
            }
        }
    }
    else
    {
        __('invalid.setting.request', $setting);
    }
}

Переменная $this->db передается через конструктор. В случае необходимости, вот он:

public function __construct($db, $data, $tpl)
{
    $this->db = $db;
    $this->tpl = $tpl;
    $this->data = $data;
    $this->data->setData('global', 'theme', $this->getSetting('theme'));
}

Кроме того, поскольку я использую базу данных, мое подключение к базе данных:

class Database
{
    private $data;

    public function __construct($data)
    {
    $this->data = $data;
    $this->conn = new MySQLi(
      $this->data->getData('database', 'hostname'), 
      $this->data->getData('database', 'username'), 
      $this->data->getData('database', 'password'), 
      $this->data->getData('database', 'database')
    );
    if ($this->conn->errno)
    {
        __('failed.db.connection', $this->conn->errno);
    }
    date_default_timezone_set('Europe/Amsterdam');
}

Я уже тестировал соединение, на 100% уверен, что он работает по назначению. Я устанавливаю вещи соединения DB в файле конфигурации:

'database' => array(
    'hostname' => '127.0.0.1',
    'username' => 'root',
    'password' => ******,
    'database' => 'wscript'
)

Теперь странно. таблица существует, существует запрошенная настройка, существует БД, но тем не менее эта ошибка не исчезнет. Здесь некоторое доказательство правильности БД:

IMG

4b9b3361

Ответ 1

Проблема заключается в следующем:

$query = $this->db->conn->prepare('SELECT value, param FROM ws_settings WHERE name = ?');
$query->bind_param('s', $setting);

Метод prepare() может возвращать false, и вы должны это проверить. Что касается того, почему он возвращает false, возможно, имена таблиц или столбцов (в SELECT или WHERE) неверны?

Кроме того, рассмотрите возможность использования чего-то вроде $this->db->conn->error_list для проверки ошибок, которые произошли при разборе SQL. (Я иногда повторяю строки операторов SQL и вставляю их в phpMyAdmin, чтобы проверить, но там определенно что-то не удается.)

Ответ 2

Каждый раз, когда вы получаете...

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

... Вероятно, из-за проблемы возникает вопрос. prepare() может возвращать FALSE (логическое), но это общее сообщение об отказе не оставляет вас в стороне от подсказок. Как вы узнаете, что не так с вашим запросом? Вы спрашиваете!

Прежде всего, убедитесь, что отчет об ошибках включен и отображается: добавьте эти две строки в начало файла (ов) сразу после вашего тэга <?php:

error_reporting(E_ALL);
ini_set('display_errors', 1);

Если ваш отчет об ошибках установлен в php.ini, вам не придется беспокоиться об этом. Просто убедитесь, что вы обрабатываете ошибки изящно и никогда не раскрываете истинные причины каких-либо проблем для ваших пользователей. Выявление истинной причины для общественности может быть приглашением на золото с гравировкой для тех, кто хочет нанести вред вашим сайтам и серверам. Если вы не хотите отправлять ошибки в браузер, вы всегда можете следить за журналами ошибок веб-сервера. Расположение журналов будет варьироваться от сервера к серверу, например, на Ubuntu журнал ошибок обычно находится в /var/log/apache2/error.log. Если вы изучаете журналы ошибок в среде Linux, вы можете использовать tail -f /path/to/log в окне консоли, чтобы видеть ошибки, как они происходят в режиме реального времени.... или как вы их делаете.

После того, как вы отделитесь от стандартной отчетности об ошибках, добавив проверку ошибок в вашем соединении с базой данных и запросах, вы получите гораздо больше информации о проблемах. Посмотрите на этот пример, где имя столбца неверно. Во-первых, код, который возвращает общее роковое сообщение об ошибке:

$sql = "SELECT `foo` FROM `weird_words` WHERE `definition` = ?";
$query = $mysqli->prepare($sql)); // assuming $mysqli is the connection
$query->bind_param('s', $definition);
$query->execute();

Ошибка является общей и не очень помогает вам в решении того, что происходит.

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

$sql = "SELECT `foo` FROM `weird_words` WHERE `definition` = ?";
if($query = $mysqli->prepare($sql)) { // assuming $mysqli is the connection
    $query->bind_param('s', $definition);
    $query->execute();
    // any additional code you need would go here.
} else {
    $error = $mysqli->errno . ' ' . $mysqli->error;
    echo $error; // 1054 Unknown column 'foo' in 'field list'
}

Если что-то не так, вы можете выплюнуть сообщение об ошибке, которое приведет вас к проблеме. В этом случае в таблице нет столбца foo, решение проблемы тривиально.

Если вы выберете, вы можете включить эту проверку в функцию или класс и расширить ее, обработав ошибки изящно, как упоминалось ранее.

Ответ 3

prepare возвращает boolean только тогда, когда он терпит неудачу, поэтому FALSE, чтобы избежать ошибки, вам нужно проверить, есть ли она True, прежде чем выполнить:

$sql = 'SELECT value, param FROM ws_settings WHERE name = ?';
if($query = $this->db->conn->prepare($sql)){
    $query->bind_param('s', $setting);
    $query->execute();
    //rest of code here
}else{
   //error !! don't go further
   var_dump($this->db->error);
}

Ответ 4

Даже если синтаксис запроса верен, подготовить может вернуть значение false, если было предыдущее утверждение и оно не было закрыто. Всегда закрывайте предыдущий оператор с помощью

$statement->close();

Если синтаксис верен, следующий запрос тоже будет работать.

Ответ 5

Другая ситуация, которая может вызвать эту проблему, - неправильное кастинг в ваших запросах.

Я знаю, это может показаться очевидным, но я столкнулся с этим, используя tablename вместо tablename. Проверьте свои запросы и убедитесь, что вы используете тот же случай, что и фактические имена столбцов в таблице.

Ответ 6

Иногда это также из-за неправильного имени таблицы или имени столбца в операторе подготовки.

Смотрите это.

Ответ 7

Вы всегда должны стараться изо всех сил, чтобы всегда помещать свои операторы в блок try catch... это всегда поможет в подобных ситуациях и даст вам понять, что не так. Возможно, имя таблицы или столбца неверно.

Ответ 8

Эта конкретная ошибка имеет очень мало общего с действительной ошибкой. Вот мой аналогичный опыт и решение...

У меня была таблица, которую я использую в своем утверждении с составным именем |database-name|.login. Я думал, что это не будет проблемой. Это была действительно проблема. Заключение в квадратные скобки решило мою проблему ([|database-name|].[login]). Итак, проблема в том, что MySQL сохранил слова (наоборот)... убедитесь, что ваши столбцы тоже не выходят из строя при таком типе ошибки...

Ответ 9

Следующие два являются наиболее вероятной причиной этой проблемы:

  1. Орфографическая ошибка в именах столбцов или таблицы
  2. Ранее установленное выражение не закрыто. Просто закройте его, прежде чем делать готовое выражение.

$stmt->close(); // <<<-----This fixed the issue for me

$stmt = $conn->prepare("Insert statement");

Ответ 10

Иногда может помочь явное указание имен столбцов таблицы (особенно в запросе вставки). Например, запрос:

INSERT INTO tableName(param1, param2, param3) VALUES(?, ?, ?)

может работать лучше, чем:

INSERT INTO tableName VALUES(?, ?, ?)

Ответ 11

Я заметил, что ошибка была вызвана тем, что я передал имена полей таблицы в виде переменных, то есть отправил:

$stmt = $this->con->prepare("INSERT INTO tester ($test1, $test2) VALUES (?,?)");

вместо:

$stmt = $this->con->prepare("INSERT INTO tester (test1, test2) VALUES (?,?)");

Обратите внимание, что имена полей таблицы содержали $ перед именами полей. Они не должны быть там такими, что $field1 должно быть field1.