I'm busy on a function that gets settings from a DB, and suddenly, I ran into this error:
Fatal error: Call to a member function bind_param() on boolean in C:\xampp2\htdocs\application\classes\class.functions.php on line 16
Normally, this would mean that I'm selecting stuff from unexisting tables and stuff. But in this case, I 'm not...
Here's the getSetting
function:
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);
}
}
The $this->db
variable is passed through a constructor. In case of need, here is it:
public function __construct($db, $data, $tpl)
{
$this->db = $db;
$this->tpl = $tpl;
$this->data = $data;
$this->data->setData('global', 'theme', $this->getSetting('theme'));
}
Also, since I'm making use of a database, my database connection:
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');
}
I've already tested the connection, 100% positive that it works as intended. I'm setting the DB connection things in a configuration file:
'database' => array(
'hostname' => '127.0.0.1',
'username' => 'root',
'password' => ******,
'database' => 'wscript'
)
Now the weird thing is; the table exists, the requested setting exists, the DB exists, but still, that error won't leave. Here's some proof that the DB is correct:
Sometimes explicitly stating your table column names (especially in an insert query) may help. For example, the query:
INSERT INTO tableName(param1,param2,param3) VALUES(?,?,?)
may work better as opposed to:INSERT INTO tableName VALUES(?,?,?)
Following two are the most probable cause of this issue:
Even when the query syntax is correct, prepare could return false, if there was a previous statement and it wasn't closed. Always close your previous statement with
If the syntax is correct, the following query will run well too.
This particular error has very little to do with the actual error. Here is my similar experience and the solution... I had a table that I use in my statement with "|database-name|.login" composite name. I thought this wouldn't be a problem. It was the problem indeed. Enclosing it inside square brackets solved my problem ("[|database-name|].[login]"). So, the problem is MySQL preserved words (other way around ;) )... make sure your columns too are not failing to this type of error scdenario...
Any time you get the...
...it is likely because there is an issue with your query. The
prepare()
might returnFALSE
(a Boolean), but this generic failure message doesn't leave you much in the way of clues. How do you find out what is wrong with your query? You ask!First of all, make sure error reporting is turned on and visible: add these two lines to the top of your file(s) right after your opening
<?php
tag:If your error reporting has been set in the php.ini you won't have to worry about this. Just make sure you handle errors gracefully and never reveal the true cause of any issues to your users. Revealing the true cause to the public can be a gold engraved invitation for those wanting to harm your sites and servers. If you do not want to send errors to the browser you can always monitor your web server error logs. Log locations will vary from server to server e.g., on Ubuntu the error log is typically located at
/var/log/apache2/error.log
. If you're examining error logs in a Linux environment you can usetail -f /path/to/log
in a console window to see errors as they occur in real-time....or as you make them.Once you're squared away on standard error reporting adding error checking on your database connection and queries will give you much more detail about the problems going on. Have a look at this example where the column name is incorrect. First, the code which returns the generic fatal error message:
The error is generic and not very helpful to you in solving what is going on.
With a couple of more lines of code you can get very detailed information which you can use to solve the issue immediately. Check the
prepare()
statement for truthiness and if it is good you can proceed on to binding and executing.If something is wrong you can spit out an error message which takes you directly to the issue. In this case there is no
foo
column in the table, solving the problem is trivial.If you choose, you can include this checking in a function or class and extend it by handling the errors gracefully as mentioned previously.
Sometimes, it is also because of a wrong table name or column name in the prepare statement.
See this:
https://www.youtube.com/watch?v=LGHdQ1bBho8