正如它听起来的那样,我的检索语句都没有按应有的方式检索数据。这很奇怪,就好像我复制了确切的查询并将其放入 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();
我收到以下错误:“ fatal error :调用非对象上的成员函数 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,请说什么,这让我发疯。
最佳答案
首先,虽然您的输入来自数据库,但您仍然不应该相信任何不是您自己输入的数据。
$result = $db->query("SELECT id, username, password FROM users WHERE email = $email");
$row = $result->fetch();
这有一个语法错误:$email
需要引号,因为它是一个字符串。
你真的确定你正在连接到 $_SERVER["SERVER_NAME"]
?
你真的应该只连接到 localhost
相反……
测试查询的一个技巧是将其包装在 if
中 block ,因为如果失败,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
为了这。事实上,对插入数据或包含用户输入的所有内容都使用 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>
这样的用户名并从最新的漏洞中获得很多乐趣。 sanitizer ~
更新:阅读您的代码后,我发现了您的问题。
$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
= 整数。
第三个是您根本不在此处绑定(bind)任何结果变量。使用准备好的查询时,您必须绑定(bind)变量。这是针对此实例的修复:
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,如果您计算使用多个查询来执行此操作。
关于php - 尝试学习 mysqli,我的语句实际上都没有返回结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15012227/