gpt4 book ai didi

php - 如何在 PHP 8 中修复这个动态 SQL 查询函数?

转载 作者:行者123 更新时间:2023-12-04 03:35:38 27 4
gpt4 key购买 nike

在我的旧项目中,我使用一个函数在进行查询时稍微“缩短”我的代码。
而不是使用通常的方法

$conn = [...]
$stmt = $conn->prepare(...)
$stmt->bind_param(...)
$stmt->execute();
$stmt->close();
$conn->close();
我有一个函数可以在我之前执行此操作,名为 dynamic_db_reader($mysqli, $param, $qry) .
它返回一个数组(或空值),如: $array[index]['column_name'] = value或者至少,这是它在以前的版本中所做的。 (在 PHP 7.4.16 中工作)
这是我的函数的代码:
/**
* Dynamically executes a given sql statement as prepared statement (?-placeholder).
* Expects correct parameters as an array to replace ?.
* Returns an array with ($arr[index]['column_name'] = value), or null.
*
* @param $ms mysqli
* @param $params array
* @param $qry string
* @return array|null
*/
function dynamic_db_reader($ms, $params, $qry){

$fields = array();
$results = array();

// Replace prefix (DBPREF in: inc/config.php)
if (strpos($qry, 'prefix_') !== false){
$qry = str_replace('prefix', DBPREF, $qry);
}

// Set charset
mysqli_set_charset($ms, 'utf8mb4');

if ($stmt = $ms->prepare($qry)){

// Dynamically bind parameters from $params
if (!isset($params) || !empty($params)){
// Parameters are set
$types = '';

foreach($params as $param){
// Set parameter data type
if (is_string($param)){
$types .= 's'; // Strings
} else if (is_int($param)){
$types .= 'i'; // Integer
} else if (is_float($param)){
$types .= 'd'; // Double/Float
} else {
$types .= 'b'; // Default: Blob and unknown types
}
}

$bind_names[] = $types;
for ($i = 0; $i < count($params); $i++){
$bind_name = 'bind' . $i;
$$bind_name = $params[$i];
$bind_names[] = &$$bind_name;
}

call_user_func_array(array($stmt, 'bind_param'), $bind_names);
}

$stmt->execute();

$meta = $stmt->result_metadata();

// Dynamically create an array to bind the results to
while ($field = $meta->fetch_field()){
$var = $field->name;
$$var = null;
$fields[$var] = &$$var;
}

// Bind results
call_user_func_array(array($stmt, 'bind_result'), $fields); // --> Error :(

// Fetch results
$i = 0;
while ($stmt->fetch()){
$results[$i] = array();
foreach($fields as $k => $v){
$results[$i][$k] = $v;
}
$i++;
}

// Close statement
$stmt->close();

if (sizeof($results) > 0){
return $results;
}
}
return NULL;
}
错误:
Fatal error:  Uncaught ArgumentCountError: mysqli_stmt::bind_result() does not accept unknown named parameters in [...]\inc\db.php:87
Stack trace:
#0 [...]\root\inc\db.php(87): mysqli_stmt->bind_result(data_key: NULL, data_value: NULL)
#1 [...]\root\inc\func\common.php(76): dynamic_db_reader(Object(mysqli), Array, 'SELECT * FROM v...')
#2 [...]\root\www\index.php(22): getTestArray()
#3 {main}
thrown in [...]\root\inc\db.php on line 87
如何修复此代码,使其也适用于 PHP 8?

最佳答案

对于如此简单的事情来说,这是一个非常长的方法。 PHP 8 添加了命名参数。当您解包用作参数的数组时,其键将用作参数名称。 mysqli_stmt::bind_result()不接受像您传递它那样的命名参数。
如果我们简化这段代码,那么它应该是这样的:

/**
* Dynamically executes a given sql statement as prepared statement (?-placeholder).
* Expects correct parameters as an array to replace ?.
* Returns an array with ($arr[index]['column_name'] = value), or null.
*/
function dynamic_db_reader(mysqli $ms, array $params, string $qry): ?array
{
// Replace prefix (DBPREF in: inc/config.php)
if (strpos($qry, 'prefix_') !== false) {
$qry = str_replace('prefix', DBPREF, $qry);
}

$stmt = $ms->prepare($qry);

// Dynamically bind parameters from $params
if ($params) {
$stmt->bind_param(str_repeat('s', count($params)), ...$params);
}

$stmt->execute();

return $stmt->get_result()->fetch_all(MYSQLI_ASSOC) ?: null;
}


mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'password', 'test');
$mysqli->set_charset('utf8mb4');

$results = dynamic_db_reader($mysqli, ['foo'], 'SELECT ?');
如果出于某种原因,您正在使用从 libmysql 客户端编译的 mysqli,那么……好吧,是时候弄清楚如何启用 mysqlnd 或切换到 PDO。
附言请确保您已启用 mysqli 错误报告。 How to get the error message in MySQLi? .此外,每次设置字符集也没有意义。建立连接后立即设置。

关于php - 如何在 PHP 8 中修复这个动态 SQL 查询函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66986315/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com