Неустранимая ошибка: вызов функции-члена 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]()
Ответы
Ответ 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
Следующие два являются наиболее вероятной причиной этой проблемы:
- Орфографическая ошибка в именах столбцов или таблицы
- Ранее установленное выражение не закрыто. Просто закройте его, прежде чем делать готовое выражение.
$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
.