OOP数据库连接中mysqli_num_rows()函数的使用问题排查
问题排查与修复方案
核心原因:构造函数逻辑错误导致$user为空
你的DB_torii类构造函数逻辑完全颠倒了:
- 实例化类时,
$this->conn初始值为null,会直接进入if (!$this->conn)分支,只执行数据库连接操作,完全不会处理POST提交的用户名和密码。 else分支只有在$this->conn已存在时才会触发,但第一次实例化时永远走不到这里,导致$this->user始终是空字符串。- 执行
SELECT password FROM admin WHERE name=''时,数据库返回0行,$num_row = 0。PHP弱类型比较中0 == null会返回true,所以你设$num_row == null时条件能成立,代码看似“正常”,但这是逻辑错误引发的巧合。
修复步骤
1. 重构构造函数逻辑
把数据库连接和POST参数处理合并,去掉无效的分支判断:
function __construct() { // 先建立数据库连接 $this->conn = new mysqli('localhost', 'root', '', 'zinuskerec'); if ($this->conn->connect_error) { die('数据库连接失败: ' . $this->conn->connect_error); } // 处理POST提交的账号密码 if (isset($_POST['username']) && isset($_POST['password'])) { $this->user = $_POST['username']; $this->passInput = hash('sha256', $_POST['password']); } else { $this->addError('未输入账号或密码'); } }
注意:构造函数不需要返回值,返回语句在构造函数中无效。
2. 修复登录逻辑的行数判断
当$user正确赋值后,查询到有效用户时$num_row会等于1,此时才进入密码验证分支:
public function login() { // 先检查是否已获取账号 if (empty($this->user)) { $this->addError('未输入账号'); header('Location: adminLogin.php'); exit; // 跳转后必须终止代码执行,避免后续逻辑干扰 } // 使用预处理语句防止SQL注入 $sql = "SELECT password FROM admin WHERE name = ?"; $sqlQuery = $this->conn->prepare($sql); $sqlQuery->bind_param('s', $this->user); // 绑定字符串类型参数 $sqlQuery->execute(); $result = $sqlQuery->get_result(); $num_row = $result->num_rows; // 直接使用mysqli_result的num_rows属性 if ($num_row == 1) { $row = $result->fetch_assoc(); $this->password = $row['password']; if ($this->password == $this->passInput) { $_SESSION['username'] = $this->user; header('Location: adminMain.php'); exit; } else { $this->addError('密码错误'); header('Location: adminLogin.php'); exit; } } else { $this->addError('用户名不存在或错误'); header('Location: adminLogin.php'); exit; } }
3. 修复其他细节问题
- 移除无用的
process方法,直接在login中使用预处理语句,彻底避免SQL注入风险。 - 所有
header跳转后必须加exit或die,防止后续代码继续执行引发异常。 - 私有变量
$sucess赋值时要加$this->,即$this->sucess = true;,否则只是创建了局部变量。
内容的提问来源于stack exchange,提问作者Petr Mášá
相关产品推荐
相关产品推荐

