提问人:sushibrain 提问时间:12/10/2014 最后编辑:Dharmansushibrain 更新时间:12/6/2022 访问量:331172
在从数据库获取设置的函数上,我遇到了错误[duplicate]
On a function that gets settings from a DB I ran into the error [duplicate]
问:
我正忙于一个从数据库获取设置的函数,突然,我遇到了这个错误:
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% 肯定它按预期工作。 我正在配置文件中设置数据库连接:
'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()
方法可以返回,您应该检查一下。至于为什么会返回,也许表名或列名(in或子句)不正确?false
false
SELECT
WHERE
此外,请考虑使用 $this->db->conn->error_list
之类的工具来检查解析 SQL 时发生的错误。(我偶尔会回显实际的 SQL 语句字符串并粘贴到 phpMyAdmin 中进行测试,但那里肯定有一些失败的地方。
评论
$query->error_list
$query->error_list
$query
error
error_list
$this->db->conn->error_list
prepare
因此,仅在失败时返回布尔值,为了避免错误,您需要在执行之前检查它是否是第一个: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);
}
任何时候你得到...
“致命错误:在布尔值上调用成员函数 bind_param()”
...这可能是因为您的查询存在问题。可能会返回(布尔值),但这个通用的失败消息不会给你留下太多线索。你如何发现你的查询有什么问题?你问!prepare()
FALSE
首先,确保错误报告已打开且可见:在开始标记之后,将以下两行添加到文件顶部:<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
如果您的错误报告已在php.ini中设置,则不必担心这一点。只要确保你优雅地处理错误,永远不要向用户透露任何问题的真正原因。向公众揭示真正原因可能是那些想要损害您的网站和服务器的人的金刻邀请。如果您不想向浏览器发送错误,您可以随时监控 Web 服务器错误日志。日志位置因服务器而异,例如,在 Ubuntu 上,错误日志通常位于 .如果要检查 Linux 环境中的错误日志,则可以在控制台窗口中查看实时发生的错误。或者当你制作它们时。/var/log/apache2/error.log
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 也可能返回 false。 始终用
$statement->close();
如果语法正确,则以下查询也将运行良好。
可能导致此问题的另一种情况是查询中的转换不正确。
我知道这听起来可能很明显,但我通过使用而不是 .检查查询,并确保使用与表中列的实际名称相同的大小写。tablename
Tablename
有时,这也是因为 prepare 语句中的表名或列名错误。
看这个。
评论
你应该总是尽可能地把你的语句放在一个trycatch块中......在这种情况下,它总是会有所帮助,并让您知道出了什么问题。也许表名或列名是错误的。
此特定错误与实际错误关系不大。这是我的类似经历和解决方案......
我有一个表,我在我的语句中使用了复合名称。我认为这不会有问题。这确实是问题所在。将其括在方括号内解决了我的问题()。所以,问题是MySQL保留了字(相反)......确保您的列也不会出现此类错误情况...|database-name|.login
[|database-name|].[login]
以下两个是此问题最可能的原因:
- 列名或表名中的拼写错误
- 以前建立的语句不会关闭。只需在进行准备好的语句之前关闭它即可。
$stmt->close(); // <<<-----This fixed the issue for me
$stmt = $conn->prepare("Insert statement");
有时,显式说明表列名称(尤其是在插入查询中)可能会有所帮助。例如,查询:
INSERT INTO tableName(param1, param2, param3) VALUES(?, ?, ?)
与以下情况相比,可能效果更好:
INSERT INTO tableName VALUES(?, ?, ?)
我注意到错误是由我将表字段名称作为变量传递引起的,即我发送了:
$stmt = $this->con->prepare("INSERT INTO tester ($test1, $test2) VALUES (?, ?)");
而不是:
$stmt = $this->con->prepare("INSERT INTO tester (test1, test2) VALUES (?, ?)");
请注意表字段名称包含在字段名称之前。他们不应该在那里,所以应该.$
$field1
field1
根据我的经验,这很好,但我弄错了数据库名称,所以,我只更改了连接参数中的数据库名称,它运行良好。bind_param
我已经定义了根路径来指示根文件夹,包括包含文件夹的路径和网站主URL的基本URL。这将用于在需要它们的地方调用它们。
评论