Hi Sixxxz,
The code in question is in /home/vol19_1/infinityfree.com/if0_35396083/htdocs/system/glyconFunc/c3636f0afa193b189ba0e840c86b1c35.php
from lines 254 to 272.
The original function is as follows:
function countRow($data)
{
global $conn;
$where = "";
if ($data["where"]) {
$where = "WHERE ";
foreach ($data["where"] as $key => $value) {
$where .= " " . $key . "=:" . $key . " && ";
$execute[$key] = $value;
}
$where = substr($where, 0, -3);
} else {
$execute[] = "";
}
$row = $conn->prepare("SELECT * FROM " . $data["table"] . " " . $where . " ");
$row->execute($execute);
$validate = $row->rowCount();
return $validate;
}
This function attempts to dynamically build a SQL PDO query based on a array of parameters, execute the query and return the row counts.
In this case we have to understand how the query is built.
The code attempts to build the query by first preparing the placeholders into a $where string and then appends to the master command in the prepare statement. However in PHP PDO, we need to bindParam after preparing the statement but before executing it, meaning there’s one more step to bind the params using the array again before executing the SQL command, this way you have filled in all the blanks.
With that in mind, please inspect this preliminary version:
<?php
function countRow($data)
{
global $conn;
$where = '';
$execute = [];
if ($data['where']) {
$where = 'WHERE ';
foreach ($data['where'] as $key => $value) {
$where .= ' ' . $key . '=:' . $key . ' && ';
}
$where = substr($where, 0, -3);
}
$row = $conn->prepare('SELECT * FROM ' . $data['table'] . ' ' . $where . ' ');
foreach ($execute as $key => $value) {
$conn->bindPAram(':' . $key, $value);
}
$row->execute();
$validate = $row->rowCount();
return $validate;
}
Here we added the part to do bindParam based on $execute (the variable you put all values in) and run $row->execute() correctly.
However there are room for improvements still, and we can tidy the code up a bit to have a cleaner syntax, better handling, type hinting and string formatting:
<?php
function countRow(array $data = []):int
{
// get connection
global $conn;
// early escape if table is not specified.
if(!array_key_exists('table', $data)){
return 0;
}
// trim the table variable
$table = trim($data['table']);
// early escape if table name is empty.
if(empty($data['table'])){
return 0;
}
// prepare the where statement if the where part exists in data.
$where = '';
if(array_key_exists('where', $data) && sizezof($data['where']) > 0){
$keys = array_keys($data['where']);
$where = implode(' ', array_map(function ($e) {
return sprintf('%s =: %s', $e, $e);
}, $keys));
$where = sprintf('WHERE %s', $where);
}
// tell sql to do the counting instead of having PHP to do,
// the count(1) method makes this run fastest as it counts 1s instead of the whole record.
$row = $conn->prepare(trim(sprintf('SELECT COUNT(1) AS c FROM %s %s', $table, $where)));
if(!empty($where)){
foreach ($data['where'] as $key => $value) {
$conn->bindPAram(sprintf(':%s', $key), $value);
}
}
// error handling with try catch
try{
// run the SQL
$row->execute();
// the count is in the first result c
return $row->fetch_results_assoc()[0]->c;
}catch(\Exception $e){
return -1;
}
}
Cheers!