You should be validating and sanitizing the variables that are not being parameterized.
When there is a strict set of acceptable values, write an array of whitelisted values and check against that.
If input is coming from a text type input or textarea, then it will be harder to validate, and you may have to settle for stripping html or characters which you deem to be out-of-bounds.
You need to be as ruthless as possible without damaging the user experience because people that may attempt to compromise your system will not be pulling any punches.
Some examples:
There is only one sort value worth receiving / using in your query. ASC
is just syntactic sugar. Because the form provides a radio input field, you don't need to bother with trimming whitespace.
$sort = $_POST['sort'] == 'DESC' ? 'DESC' : '';
Unless you are accepting the offset and row count as a single value, the limit value MUST be an integer. Since your form provides a text input field for this, it is possible that a well-intended user may accidentally pass whitespace. For this reason, it would be a sensible inclusion to trim the value before validating it.
$limit = ctype_digit(trim($_POST['limit'])) ? (int)$_POST['limit'] : '';
filter
and $order
come from select input fields. This means you know exactly which values to expect. A lookup array will do the job in a tidy fashion.
$filterLookup = ['filter1', 'filter2', 'filter3'];
$filter = in_array($_POST['filter'], $filterLookup) ? $_POST['filter'] : '';
In your project structure, you might even design a single reference point for filter
and order
column values so that everything stays in sync. You wouldn't want your lookup array to deviate from your form's select options -- that would lead to user frustration.
As for how you treat values that do not fall within the predicted range -- that is up to you. You should inform the user when the request could not be processed due to invalid/missing data and let them know how they can fix up their submission. In some cases, you may wish to simply ignore faulty values and proceed with the query construction with that segment omitted -- again, that is your call.
p.s. Consider these adjustments for the sake of readability (while this largely comes down to personal style, it is generally a good idea to write code that doesn't require horizontal scrolling to read):
$result = $search->search(
$_POST['filter'],
$_POST['input'],
$_POST['type'],
$_POST['order'],
$_POST['sort'],
$_POST['limit']
);
and
function search($filter, $input, $type, $order, $sort, $limit) {
$stmt = $this->conn->prepare(
"SELECT Title, Type, Youtube, Score, Ratings, Singer, ID
FROM song
WHERE $filter LIKE CONCAT('%', ?, '%')
AND Type = ?
ORDER BY $order $sort
LIMIT $limit"
);
$stmt->execute([$input, $type]);
return $stmt->fetchall();
}
Regarding your comment about sanitizing limit values, I recommend a min-max sandwich after casting the input as an integer... (Demo)
$inputs = ['7', '54', '3', 'foo'];
foreach ($inputs as $input) {
echo "---\n$input >>> ";
$sanitized = min(max((int)$input, 5), 50);
var_dump($sanitized);
}
Output:
---
7 >>> int(7)
---
54 >>> int(50)
---
3 >>> int(5)
---
foo >>> int(5)