Я сделал следующее наблюдение на примере, который вы разместили: все, что вы хотите сделать, - это заменить токены, например C++
, токеном формы skill=C++
, остальная часть запроса не изменится.Если это не всегда так, вам может потребоваться более сложное решение, но если этого достаточно для вас, должно работать следующее:
$expr = 'C++ AND ((UML OR Python) OR (not Perl))';
// remove tokens that will not be replaced, here `(`, `)`, and `not`
$trimmed = str_replace(['(', ')', 'not'], ['', '', ''], $expr);
// split string based on the keywords `AND` and `OR` (case insensitive)
// keywords will also not be replaced
$tokens = preg_split('/AND|OR/i', $trimmed);
// create replacement tokens without leading/trailing whitespace
$replacementTokens = [];
foreach ($tokens as &$token) {
$token = trim($token);
$replacementTokens[] = "skill=$token";
}
// replace tokens and construct the query
$where = str_replace($tokens, $replacementTokens, $expr);
$query = "SELECT * FROM candidates WHERE $where";
Как уже говорилось, это решение может не работать, если вам нужно более сложное поведение,Вам также может понадобиться расширить списки ключевых слов.Но для предоставленного вами простого варианта использования он избавляет от необходимости фактически анализировать запрос.
В заключение отметим, что вы дезинфицируете свои пользовательские входные данные, поэтому вы не подвержены SQL-инъекциям.