究竟是什么声音,我的检索语句都没有检索到应有的数据。这很奇怪,好像我复制了确切的查询并将其放入phpMyAdmin并在那里运行它,它会返回结果。
插入语句等工作,例如:
// On first connect to database, create a user to hold data for users not logged in
$result = $db->query("SELECT id FROM users WHERE id = 1");
if ($result->num_rows == 0) {
$db->query("INSERT INTO users (id, username, email, password) VALUES (1, 'anonymous', 'anonymous', '" . password_hash("...", PASSWORD_BCRYPT) . "')");
}
用户按预期输入。
但如果我发表如下声明:
$result = $db->query("SELECT id, username, password FROM users WHERE email = $email");
$row = $result->fetch();
我收到以下错误:“致命错误:在非对象上调用成员函数fetch()”
在phpMyAdmin中运行完全相同的语句会按预期返回该行。
但它只适用于一个领域:
if ($result = $db->query("SELECT username, wins, losses FROM users ORDER BY wins DESC LIMIT 10")) {
while ($row = $result->fetch_assoc()) {
echo "<tr><td>" . $row["username"] . "</td> <td>" . $row["wins"] . "</td> <td>" . $row["losses"] . "</td></tr>\n";
}
}
返回预期结果。不过我不知道为什么。
我不确定我的文件结构是否重要,我有一个我需要的config.php文件,它有连接信息。其余的都在我的index.php文件中。
这是config.php:
<?php
$db_host = $_SERVER["SERVER_NAME"];
$db_user = "...";
$db_pass = "...";
$db_database = "hangman";
$db = new mysqli($db_host, $db_user, $db_pass, $db_database);
if ($db->connect_error) {
echo "Could not connect to database.";
exit;
}
// On first connect to database, create a user to hold data for users not logged in
$result = $db->query("SELECT id FROM users WHERE id = 1");
if ($result->num_rows == 0) {
$db->query("INSERT INTO users (id, username, email, password) VALUES (1, 'anonymous', 'anonymous', '" . password_hash("...", PASSWORD_BCRYPT) . "')");
}
?>
我可以包含更多我的PHP,请说出来,这只会让我发疯。
答案 0 :(得分:2)
我不确定错误到底是什么。
难怪。你没有要求这个。
运行查询时,您必须始终检查错误
$sql = "SELECT wins, losses FROM users WHERE id = 1";
$res = $db->query($sql) or trigger_error($db->error." [$sql]");
$row = $res->fetch_assoc();
答案 1 :(得分:2)
首先,虽然您的输入来自数据库,但您仍然不应该信任您未自行输入的任何数据。
$result = $db->query("SELECT id, username, password FROM users WHERE email = $email");
$row = $result->fetch();
这有一个语法错误:$email
需要引号,因为它是一个字符串。
您确定要连接到$_SERVER["SERVER_NAME"]
吗?
您应该真正连接到localhost
而不是......
测试查询的提示是将其包装在if
块中,因为如果失败,则返回FALSE
而不是对象。您无法拨打false->fetch()
。
if ($result = $db->query($sql)) {
//do stuff, fetch data, etc.
} else {
if (DEBUG) { // define('DEBUG', 1);
trigger_error("Query Failed; Fix it: " . htmlspecialchars($sql));
} else {
header("Location: /oops.php");
}
}
此外,请使用prepare
。事实上,使用准备插入数据的所有内容,或包括用户输入,句点。并在之前定义任何循环。
if ($x = $db->prepare("SELECT id, username, password FROM users WHERE email = ?")) {
$x->bind_param("s", $email);
$x->execute();
$x->bind_result($id, $user, $pass);
$x->fetch();
}
Fetch并不完全符合您的习惯。它在执行查询后获取数据。 fetch_assoc
将从结果对象中获取关联数组。
此外,每次有人加载页面时,查询数据库users.id = 1
都不是一个好主意。坚持在安装脚本中。并使匿名用户拥有一个不可能的密码(而不是$2y$13$<hash>
它将是Nope, not happenin'
或其他东西。
此外,您直接从数据库回显HTML。如果你不清理,我可以创建一个像<script src=""></script>
这样的用户名,并对最新的漏洞利用有很多乐趣。消毒〜
更新:阅读完代码后,我发现了您的问题。
$stmt1 = $db->prepare("SELECT wins FROM users WHERE id = ?");
$stmt2 = $db->prepare("SELECT losses FROM users WHERE id = ?");
$stmt1->bind_param($_SESSION["id"]);
$stmt2->bind_param($_SESSION["id"]);
$stmt1->execute();
$stmt2->execute();
$row1 = $stmt1->fetch();
$row2 = $stmt2->fetch();
这里有三个问题 1 。
第一个问题是 您一次只能在给定连接上进行一次预备调用 。我很确定这是因为它是一个阻塞的API调用。如果我错了,请纠正我。
第二个是 您未指定bind_param
来电 的类型。您必须为此处指定的任何内容指定类型。 s
=字符串,i
=整数。
第三个是 你根本没有绑定任何结果变量 。使用准备好的查询时,必须绑定变量。这是此实例的修复:
if ($query = $db->prepare("SELECT wins, losses FROM users WHERE id = ?")) {
$query->bind_param("s", $_SESSION["id"]);
$query->execute();
$query->bind_result($wins, $losses);
if (!$query->fetch()) { // fetch one row from database.
logout(); // or equiv.
}
} else {
if (DEBUG) {
echo "Malformed SQL or In-use thread. SQL: <sql here>";
} else {
header("Location: /oops.php");
}
}
1。如果您计算多次查询,则为4。
答案 2 :(得分:1)
您的查询语法错误会导致查询失败,这意味着$ result不会是结果对象。第一个查询将失败,因为您没有在电子邮件中添加引号:
SELECT id, username, password FROM users WHERE email = $email
应该是:
SELECT id, username, password FROM users WHERE email = '$email'
在您的查询之后,您应该输入如下内容:
if ($result->errno!=0){
echo $result->error;
exit(0)
}
$row=$result->fetch_assoc();
//etc.
答案 3 :(得分:0)
@hiroto是对的。 如果没有结果,那么就没有对象,这就是为什么你在非对象上调用方法时会遇到致命的错误。正如他所提到的,SQL查询存在问题,并且需要引用电子邮件,因为它是一个字符串。否则MySQL将失败并出现错误。
另外,mysqli结果对象没有fetch()方法,这就是他建议fetch_assoc();
的原因要获得结果,您需要引用电子邮件,以便获得结果对象,并在访问数据时执行循环:
$result = $db->query("SELECT id, username, password FROM users WHERE email = '$email'");
while($row = $result->fetch_assoc())
{
print_r($row);
}
或通过键直接提取数据:
$result = $db->query("SELECT id, username, password FROM users WHERE email = '$email'");
$row = $result->fetch_assoc();
echo $row['username'];