I am used to using parameterised statements but in this statement the number of the parameters can change depending on the number of words in a search string.
So "food" = 1 param, "some food" = 2, "lots of food" = 3 etc etc
I have basically set up a query to allow for searching of a website, to improve functionality i have made it possible to search certain words of columns without it have to be a perfect match.
For example, i concat a club name and its city so;
Name: Mint Club,
City: Leeds
Col: Mint Club Leeds
Searching: 'Mint Leeds' would normally result in the row not being found. But with this modification it works.
With the unknown number of parameters i basically want to know how to secure my statement as i think its still open to sql injection.
Code Below:
$keystring = $mysqli->real_escape_string($_POST["s"]);
$key = strtoupper($keystring);
$key_arr = explode(" ", $key);
$num_key = count($key_arr);
if($num_key >= 2){
$where = '';
foreach($key_arr as $val){
$where .= "(CONCAT(name,' ',city) LIKE '%".$val."%') AND ";
}
$where = substr($where, 0, -4);
$clubWhere = $where;
}
else{
$key = "%".$key."%";
$clubWhere = "(CONCAT(name,' ',city) LIKE '".$key."')";
}
$search_stmt = $mysqli->prepare("SELECT id, name, type AS 'col3', city AS 'col4', 'Club' AS 'table' FROM studentnights_clubs WHERE ".$clubWhere."
UNION
SELECT id, name, description AS 'col3', image AS 'col4', 'Event' AS 'table' FROM studentnights_events WHERE UCASE(name) LIKE ?
UNION
SELECT id, name, '' AS 'col3', '' AS 'col4', 'Genre' AS 'table' FROM studentnights_music WHERE UCASE(name) LIKE ?
ORDER BY
CASE
WHEN name LIKE ? THEN 1
WHEN name LIKE ? THEN 3
ELSE 2
END
LIMIT 10");
$search_stmt->bind_param('ssss', $key, $key, $key, $key);
$search_stmt->execute();
$search_stmt->store_result();
$search_stmt_num = $search_stmt->num_rows;
$search_stmt->bind_result($id, $name, $col3, $col4, $table);