【问题标题】:PHP devide fetching results between fetch_all() and fetch_array() [duplicate]PHP在fetchall()和fetch array()之间划分获取结果[重复]
【发布时间】:2019-08-03 18:37:16
【问题描述】:

PHP 无法拆分这两种获取类型,我正在尝试构建一个安全的登录脚本...如果我删除 //Login checker 部分,代码运行良好,当我删除 //Security 部分时,其他代码运行也很好,但是当我尝试同时运行它时,它会显示这个错误:

Fatal error: Uncaught Error: Call to a member function fetch_all() on bool in xxxFilenamexxx.php://Number of line points to fetch_all() row
stack trace:
#0 {main}
thrown in xxxFilenamexxx.php//Same line number

这是我的代码:

//Login checker
        $loginTrySql = "CALL tryLogUserIn('$typedUsername', '$typedPassword', '".$_SERVER['REMOTE_ADDR']."');";
        $loginTryResult = $conn->query($loginTrySql);
        if ($loginTryResult->num_rows == 1) {
            $data["statusi"] = 1;
            $data["tries"] = 0;
            //data to fetch for log in
        } else {
            //Security part
            $data["statusi"] = 2;
            $checkUserSql = "CALL securityCheck('$typedUsername', '$typedPassword', '".$_SERVER['REMOTE_ADDR']."', @tries_number);";
            $conn->query($checkUserSql);
            $checkUserSql = "SELECT @tries_number AS tries";
            $checkUserResult = $conn->query($checkUserSql);
            $securityRow = $checkUserResult->fetch_all(MYSQLI_ASSOC);
            $data["tries"] = $securityRow[0]['tries'];
        }
        echo json_encode($data);

【问题讨论】:

  • 这似乎是错误的逻辑,并且可能是可注入的。如果你同时有 2 个执行,@tries_number 不会被另一个执行覆盖吗?
  • 通过使用存储过程,默认语法是这样的,你给一个参数来保存一个输出,然后在数据库响应后给那个参数一个值,你可以使用它......问题不是同时执行2次吗,理论上和实践上你可以同时执行2次以上,但问题是我提到的函数fetch_all()不接受!
  • 布尔值意味着$checkUserResult 执行失败,因此使用错误报告。 php.net/manual/en/mysqli.error.php
  • 我编写了报告代码,现在它显示如下: 错误消息:命令不同步;您现在无法运行此命令。比它显示上一个错误...
  • 我正在考虑以一种方式尝试它:执行第一个sql,而不是关闭连接并再次打开第二部分sql的连接,我不知道这是否会影响运行时间?跨度>

标签: php oop mysqli


【解决方案1】:

Call to a member function fetch_all() on bool 表示您调用->fetch_all(...) 的东西实际上是一个布尔变量。

那是 $checkUserResult - 可以是布尔值 false,并且永远不会签入您的代码。

你应该检查:

            $checkUserResult = $conn->query($checkUserSql);
            if ($checkUserResult === false) {
               handle_error_somehow("Error is: " . $conn->error);
            } else {
               $securityRow = $checkUserResult->fetch_all(MYSQLI_ASSOC); 
               ...
            }

此外,如果您在每个 $conn->query 之后检查错误,您可能会发现那里到底发生了什么。

顺便说一句,将原始用户输入插入 SQL 是不安全的!至少要转义字符串:

$checkUserSql = "CALL securityCheck('" . $conn->real_escape_string($typedUsername)  
                . "', '" . $mysqli->real_escape_string($typedPassword) 
                . "', '" . $mysqli->real_escape_string($_SERVER['REMOTE_ADDR']) 
                . "', @tries_number);";

【讨论】:

  • 有两个 SQL 语句,如果我删除其中一个,其他的工作...谢谢顺便说一句
  • 那么,什么错误文本,什么时候不起作用?
  • 就像我提到的那样,如果我只是删除 $loginTrySql 或 $checkUserSql 它就像一个魅力没有错误,但我需要它们一起而不是我提到的错误显示...
  • 谢谢,@Dharman,但你最好向 OP 解决这个问题。在我的示例中,只是快速尝试解决问题,你是对的,应该使用参数化查询。但在这个例子中,转义就足够了,因为所有值都用作引号中的字符串。 转义是不够的当转义值被放置为数字常量时发生,不带引号。
  • @FlamurBeqiraj 那么,您能告诉我们您的查询中的错误是什么吗?在$conn->query() 之后的$conn->error 里面是什么返回了false
猜你喜欢
  • 1970-01-01
  • 2014-01-04
  • 2016-11-23
  • 2014-11-05
  • 2018-10-24
  • 1970-01-01
  • 1970-01-01
  • 2017-05-03
  • 2023-04-01
相关资源
最近更新 更多