Я занят функцией, которая получает настройки из БД, и внезапно я столкнулся с этой ошибкой:
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' )
Теперь странно. таблица существует, существует запрошенная настройка, существует БД, но тем не менее эта ошибка не исчезнет. Вот несколько доказательств правильности БД:
Проблема заключается в следующем:
$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 для тестирования тоже, но там определенно что-то не удается).
Каждый раз, когда вы получаете …
«Неустранимая ошибка: вызов функции-члена bind_param () в boolean»
… вероятно, потому что есть проблема с вашим запросом. Команда 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
, решение проблемы тривиально.
Если вы выберете, вы можете включить эту проверку в функцию или класс и расширить ее, обработав ошибки изящно, как упоминалось ранее.
prepare
return 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); }
Даже если синтаксис запроса верен, подготовка может вернуть false, если было предыдущее утверждение, и оно не было закрыто. Всегда закрывайте предыдущий оператор
$statement->close();
Если синтаксис верен, следующий запрос тоже будет работать.
Другой ситуацией, которая может вызвать эту проблему, является неправильное кастинг в ваших запросах.
Я знаю, это может показаться очевидным, но я столкнулся с этим, используя tablename
вместо Tablename
. Проверьте свои запросы и убедитесь, что вы используете тот же случай, что и фактические имена столбцов в таблице.