A query built by joining strings together mixes your instructions with someone else's data. The database cannot tell which is which - so a value chosen carefully stops being a value and becomes part of the question.
// wrong, and it is wrong even if you escape
$sql = "SELECT * FROM users WHERE email = '" . $email . "'";
The fix is not escaping
Escaping tries to make dangerous data safe. Prepared statements make the data ARRIVE SEPARATELY, so it can never be read as instructions at all. The database is told the question first and the values afterwards.
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
What a placeholder cannot be
A placeholder stands for a VALUE. It cannot stand for a table name, a column name or a direction - those are part of the question. If they must come from input, check them against a list you wrote.
$allowed = ['created_at', 'total', 'status'];
$sort = in_array($in, $allowed, true) ? $in : 'created_at';
$sql = "SELECT * FROM orders ORDER BY $sort DESC";
Find the ones you have
grep -rn "SELECT.*\$_\(GET\|POST\|REQUEST\)" --include="*.php" . | head
Any query with a superglobal inside the string is the pattern. There are usually a handful and they are usually old.
And the second line
Give the application user only what it needs - four verbs on one database. A successful injection through an account that cannot drop a table does far less than one through an account that can.