从函数返回的 $stmt 与函数内部不同
$stmt returned from function is different than inside the function
这是我创建数据库连接的函数:
function get_db_connection()
{
$host = "127.0.0.1:3306";
$username = "root";
$password = "";
$db = "crm";
return mysqli_connect($host, $username, $password, $db);
}
这是我使用查询的函数:
function query_user_by_username($username)
{
$conn = get_db_connection();
$stmt = $conn->prepare("SELECT * FROM `users` WHERE `username`=?");
$stmt->bind_param("s", $username);
$stmt->execute();
//var_dump($stmt->get_result()->fetch_assoc());
return $stmt;
}
当我在函数内部执行 var_dump
时,我得到 NULL
,这对于当前情况来说是非常好的响应。
但是,当我从另一个地方调用这个函数时,在执行相同的 var_dump
.
时出现错误
示例代码:
require_once(__DIR__ . '/../../db/dbh.inc.php');
$db_response = query_user_by_username("zxc");
var_dump($db_response->get_result()->fetch_assoc());
执行此操作时,出现以下错误:
Fatal error: Uncaught Error: Call to a member function fetch_assoc() on boolean in /opt/lampp/htdocs/src/signinscreen/repo/signin.inc.php:17 Stack trace: #0 {main} thrown in /opt/lampp/htdocs/src/signinscreen/repo/signin.inc.php on line 17
出于某种原因,函数内部的 $stmt->get_result()
是一个实际的 object
但当从函数返回时,它是 bool
.
为什么?
当您调用 get_db_connection()
时,它会创建一个新的 mysqli 实例 class 并打开与 MySQL 服务器的连接。只要您有一个指向它的 PHP 变量,这个对象就会存在。在您的情况下,连接仅在 query_user_by_username()
函数的范围内有效。
mysqli 中的准备语句默认生成无缓冲的结果。结果不会自动从 MySQL 服务器获取,您需要调用 get_result()
、store_result()
或逐行获取它们。要从服务器获取结果集,连接必须打开。
当您离开 query_user_by_username()
函数时,PHP 将关闭连接并丢弃所有剩余结果。当您尝试在函数外部使用 get_result()
获取结果集时,由于连接已关闭,因此没有可获取的结果。
要解决此问题,您应该将 mysqli 连接作为参数传递给函数。
function query_user_by_username(mysqli $conn, $username)
{
$stmt = $conn->prepare("SELECT * FROM `users` WHERE `username`=?");
$stmt->bind_param("s", $username);
$stmt->execute();
return $stmt;
}
那么您应该确保只要您的代码需要,连接就会一直存在。实际上,这意味着您应该只创建一个 mysqli 实例 class 并将其作为参数传递给需要它的函数。
require_once(__DIR__ . '/../../db/dbh.inc.php');
$conn = get_db_connection();
$db_response = query_user_by_username($conn, "zxc");
var_dump($db_response->get_result()->fetch_assoc());
如您所见,mysqli 是一个低级 API,这使得处理数据库操作变得困难。因此,最好使用 PDO。如果您希望继续使用 mysqli,那么您可以考虑编写一个 或以一种永远不会将底层 mysqli 函数暴露给您的业务层的方式编写您的函数。例如:
function query_user_by_username(mysqli $conn, $username): ?array
{
$stmt = $conn->prepare("SELECT * FROM `users` WHERE `username`=?");
$stmt->bind_param("s", $username);
$stmt->execute();
// only return the data, not the mysqli object
return $stmt->get_result()->fetch_assoc()
}
这是我创建数据库连接的函数:
function get_db_connection()
{
$host = "127.0.0.1:3306";
$username = "root";
$password = "";
$db = "crm";
return mysqli_connect($host, $username, $password, $db);
}
这是我使用查询的函数:
function query_user_by_username($username)
{
$conn = get_db_connection();
$stmt = $conn->prepare("SELECT * FROM `users` WHERE `username`=?");
$stmt->bind_param("s", $username);
$stmt->execute();
//var_dump($stmt->get_result()->fetch_assoc());
return $stmt;
}
当我在函数内部执行 var_dump
时,我得到 NULL
,这对于当前情况来说是非常好的响应。
但是,当我从另一个地方调用这个函数时,在执行相同的 var_dump
.
示例代码:
require_once(__DIR__ . '/../../db/dbh.inc.php');
$db_response = query_user_by_username("zxc");
var_dump($db_response->get_result()->fetch_assoc());
执行此操作时,出现以下错误:
Fatal error: Uncaught Error: Call to a member function fetch_assoc() on boolean in /opt/lampp/htdocs/src/signinscreen/repo/signin.inc.php:17 Stack trace: #0 {main} thrown in /opt/lampp/htdocs/src/signinscreen/repo/signin.inc.php on line 17
出于某种原因,函数内部的 $stmt->get_result()
是一个实际的 object
但当从函数返回时,它是 bool
.
为什么?
当您调用 get_db_connection()
时,它会创建一个新的 mysqli 实例 class 并打开与 MySQL 服务器的连接。只要您有一个指向它的 PHP 变量,这个对象就会存在。在您的情况下,连接仅在 query_user_by_username()
函数的范围内有效。
mysqli 中的准备语句默认生成无缓冲的结果。结果不会自动从 MySQL 服务器获取,您需要调用 get_result()
、store_result()
或逐行获取它们。要从服务器获取结果集,连接必须打开。
当您离开 query_user_by_username()
函数时,PHP 将关闭连接并丢弃所有剩余结果。当您尝试在函数外部使用 get_result()
获取结果集时,由于连接已关闭,因此没有可获取的结果。
要解决此问题,您应该将 mysqli 连接作为参数传递给函数。
function query_user_by_username(mysqli $conn, $username)
{
$stmt = $conn->prepare("SELECT * FROM `users` WHERE `username`=?");
$stmt->bind_param("s", $username);
$stmt->execute();
return $stmt;
}
那么您应该确保只要您的代码需要,连接就会一直存在。实际上,这意味着您应该只创建一个 mysqli 实例 class 并将其作为参数传递给需要它的函数。
require_once(__DIR__ . '/../../db/dbh.inc.php');
$conn = get_db_connection();
$db_response = query_user_by_username($conn, "zxc");
var_dump($db_response->get_result()->fetch_assoc());
如您所见,mysqli 是一个低级 API,这使得处理数据库操作变得困难。因此,最好使用 PDO。如果您希望继续使用 mysqli,那么您可以考虑编写一个
function query_user_by_username(mysqli $conn, $username): ?array
{
$stmt = $conn->prepare("SELECT * FROM `users` WHERE `username`=?");
$stmt->bind_param("s", $username);
$stmt->execute();
// only return the data, not the mysqli object
return $stmt->get_result()->fetch_assoc()
}