试图学习mysqli,我的所有陈述都没有实际返回结果

时间:2013-02-21 21:06:11

标签: php mysql mysqli

究竟是什么声音,我的检索语句都没有检索到应有的数据。这很奇怪,好像我复制了确切的查询并将其放入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 个答案:

答案 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'];