mysqli_query返回结果对象字段为null但可获取数据及num_rows判断失效的技术问询
咱们一步步拆解你遇到的核心问题:
1. 为什么日志里的$result对象属性全是null,但实际能获取到记录?
这是因为**mysqli_result是特殊的数据库结果对象,它的属性(比如num_rows、current_field等)并非普通可序列化的公共属性**。当你用json_encode()序列化它时,只能看到对象的表面结构,无法读取到它内部维护的真实数据(比如查询到的行数)。
你看到的日志输出只是json_encode()无法正确解析该对象后的“假象”,实际这个$result对象是有效的——所以你调用mysqli_fetch_assoc($result)时能拿到正确的用户数据。如果要在日志里查看真实的行数,直接输出$result->num_rows就行,别用json_encode():
error_log("Debug execute_db:: num_rows: " . $result->num_rows);
2. 为什么判断代码if (!$result || !$result->num_rows)无法达到预期效果?
看你给出的execute_db函数定义,发现了关键问题:这个函数没有返回查询结果!
你的函数里执行了mysqli_query()得到了$result,但最后没有用return $result;把结果返回给调用方。这意味着你在外面执行$result = execute_db(...)时,$result其实是PHP函数默认返回的null——这就会导致你的判断代码直接触发!$result的条件抛出异常,但你又说能拿到数据,说明你实际代码里可能漏写了return语句(或是测试时的小失误)。
修复方案:
首先,修改execute_db函数,确保它返回查询结果,同时增加错误处理:
function execute_db($query) { $connection = db_connect(); // 执行查询并检查是否成功 $result = mysqli_query($connection, $query); if (!$result) { error_log("Database query failed: " . mysqli_error($connection)); mysqli_close($connection); return false; } // 打印真实的行数到日志 error_log("Debug execute_db:: num_rows: " . $result->num_rows); error_log("Debug execute_db:: query: " . $query); // 记得关闭数据库连接(如果连接是复用的,可根据实际逻辑调整) mysqli_close($connection); // 返回结果对象给调用方 return $result; }
然后,调整你的判断代码,确保逻辑正确且避免PHP错误:
$result = execute_db("SELECT id FROM usuarios WHERE email = '$email'"); // 先检查查询是否成功,再检查是否有数据 if (!$result || $result->num_rows === 0) { throw new Exception(gettext("No existe una cuenta asociada a ese correo")); } // 然后获取数据 $user = mysqli_fetch_assoc($result);
额外建议:避免SQL注入风险
你的SQL语句直接把$email拼接到查询字符串里,存在严重的SQL注入风险。建议改用预处理语句:
function execute_db($query, $params = []) { $connection = db_connect(); $stmt = mysqli_prepare($connection, $query); if (!$stmt) { error_log("Prepare failed: " . mysqli_error($connection)); mysqli_close($connection); return false; } // 如果有参数,绑定参数并执行 if (!empty($params)) { $types = str_repeat('s', count($params)); // 假设都是字符串类型,可根据实际调整 mysqli_stmt_bind_param($stmt, $types, ...$params); if (!mysqli_stmt_execute($stmt)) { error_log("Execute failed: " . mysqli_stmt_error($stmt)); mysqli_stmt_close($stmt); mysqli_close($connection); return false; } $result = mysqli_stmt_get_result($stmt); } else { $result = mysqli_query($connection, $query); } // 后续日志和返回逻辑 error_log("Debug execute_db:: num_rows: " . $result->num_rows); mysqli_close($connection); return $result; } // 调用方式 $result = execute_db("SELECT id FROM usuarios WHERE email = ?", [$email]);
这样能有效防止SQL注入,让代码更安全。
内容的提问来源于stack exchange,提问作者Jorge Palacios Zaratiegui

