【问题标题】:Prepared Statement; fetch() or fetch_all()? Issue with While Statement准备好的声明; fetch() 还是 fetch_all()? While 语句的问题
【发布时间】:2014-05-13 16:22:35
【问题描述】:

我正在尝试调试我准备好的语句代码,但遇到了一些问题。使用以下脚本时,我在浏览器中看到“测试一”和“测试二”回显,但没有“测试三”;我的 ->fetch() 语句似乎不起作用。没有错误。

if (empty($login_errors)) { // OK to proceed!

echo 'test one';

$pas = get_password_hash($p);
$loginQuery = $dbc->prepare("SELECT id, username, type FROM user WHERE (email=? AND pass=?)");
$loginQuery->bind_param('ss',$e,$pas);
$loginQuery->execute();
$loginQuery->bind_result($id,$username,$type);

echo 'test two';

while($loginQuery->fetch()){

echo 'test three';

$idRow = $id;
$usernameRow = $username;

$_SESSION['user_id'] = $idRow[0];
$_SESSION['username'] = $usernameRow[0];
} 
echo 'test four';
}

我的第一个想法是当只有一个字段被选择(一个绑定结果)时使用->fetch()。我尝试使用while($loginQuery->fetch_all()){,因为我有三个($loginQuery->bind_result($id,$username,$type);),但这会带来 HTTP 500 错误。这种想法正确吗? fetch() 一个,fetch_all() 多个?

为什么两个 fetch 都不起作用?你能看出我的代码有什么问题吗?

显示“测试四”。这表明查询没有返回任何数据。这很令人困惑,因为在这个准备好的语句之前,我使用了连接并且下面的工作没有任何问题:

$q = "SELECT id, username, type, IF(date_expires >= NOW(), true, false) FROM user WHERE (email='$e' AND pass='"  .  get_password_hash($p) .  "')";      
$r = mysqli_query ($dbc, $q);

【问题讨论】:

  • 您的语法看起来正确。为什么不在循环之后添加echo 'test four';,这将表明您的查询没有返回任何结果?如果您没有看到额外的测试,那么这意味着您的脚本正在悄然死亡,您需要打开/打开error_reporting。此外,您应该至少检查 prepare() 和 execute() 的返回值,它们都可能在不停止脚本执行的情况下失败。
  • 谢谢。显示“测试四”,并建议没有来自 SQL 查询的结果。这很令人困惑,因为我最初的未准备好的声明(如下)运行良好。我已经修改了问题以包括更新的工作。

标签: php prepared-statement fetch


【解决方案1】:

这种想法正确吗? fetch() 一个,fetch_all() 多个?

这实际上是两个不同对象的两种不同方法。

  • fetch() 属于 mysqli 语句对象,使用丑陋的方法将查询结果分配给全局变量。 可以循环运行。循环是一种您可以多次获取单行的东西。因此,使用 fetch() 获取许多记录并没有什么矛盾
  • fetch_all() 属于 mysqli 结果对象,只是一个语法糖,在循环中为您运行 fetch_assoc()。

【讨论】:

    【解决方案2】:

    这样的事情应该可以工作:

    $loginQuery = $dbc->stmt_init();
    $loginQuery = $loginQuery->prepare("SELECT id, username, type FROM user WHERE LOWER(email) = LOWER(?) AND pass = ?");
    $loginQuery->bind_param('ss',$e,$pas);
    $loginQuery->execute();
    $results = $loginQuery->get_result();
    if($results->num_rows > 0)
    {
        $row = $results->fetch_assoc();
        $user_name = $row['username'];
        $user_id = $row['id']; 
    
    
        $_SESSION['user_id'] = $user_id;
        $_SESSION['username'] = $user_name;
    }
    else
    {
        echo "no rows returned, bad username and password.";
    }
    

    假设你的$dbc是一个mysqli对象,你还需要在prepare前调用stmt_init():

    $loginQuery = $dbc->stmt_init();
    

    还通过使用 LOWER() 使查询对电子邮件不区分大小写,您希望在登录和注册时执行此操作。这样就不会有人在 email@email.com 上注册,然后其他人在 EMAIL@email.com 上注册。您应该检查他们注册的电子邮件是否与您数据库中的电子邮件不匹配,并且在检查时使用 mysql LOWER() 函数进行比较。

    上面的代码会得到结果集中的第一行。如果您需要获取所有行,那么您就走在了正确的轨道上。但你必须这样做:

    $usersQuery = $dbc->prepare("SELECT id, username, type FROM user");
    $usersQuery->execute();
    $results = $usersQuery->get_result();   
    if($results->num_rows > 0)
    {
        while($row = $results->fetch_assoc())
        {
            $user_id = $row['id'];
            $user_name = $row['username'];
            $user_type = $row['type'];
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-02
      • 2011-07-13
      • 2014-06-30
      • 1970-01-01
      • 1970-01-01
      • 2014-01-20
      • 2019-07-02
      • 1970-01-01
      相关资源
      最近更新 更多