In my older projects, I used a function to 'shorten' my code a bit when doing queries.
Instead of using the usual approach of
$conn = [...]
$stmt = $conn->prepare(...)
$stmt->bind_param(...)
$stmt->execute();
$stmt->close();
$conn->close();
I got a function to do that fore me, called dynamic_db_reader($mysqli, $param, $qry)
.
It returns an array (or null) like: $array[index]['column_name'] = value
Or at least, that's what it used to do in previous versions. (Worked in PHP 7.4.16)
Here is the code to my function:
/**
* 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;
}
The error:
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
How can I fix this code, so that it works in PHP 8 too?