1

听起来确实如此,我的检索语句都没有按应有的方式检索数据。这很奇怪,好像我复制了确切的查询并将其放入 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,请说什么,这让我发疯。

4

4 回答 4

2

我不确定错误到底是什么。

难怪。你没有要求这个。
运行查询时必须始终检查错误

$sql = "SELECT wins, losses FROM users WHERE id = 1";
$res = $db->query($sql) or trigger_error($db->error." [$sql]");
$row = $res->fetch_assoc();
于 2013-02-21T19:57:53.670 回答
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为此使用 a 。实际上,对插入数据或包含用户输入的所有内容都使用 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,如果您计算使用多个查询来执行此操作。

于 2013-02-21T21:20:36.080 回答
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.
于 2013-02-21T21:10:10.627 回答
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'];
于 2013-02-22T01:13:14.660 回答