Хорошо, поэтому я довольно новичок в php и mysql. Я создаю php-интерфейс для базы данных mysql. Я использую драйвер PDO для доступа к базе данных, поскольку он предотвращает атаки SQL-инъекций. Пока все было хорошо, пока я не пришел к этой проблеме. У меня есть функция поиска, в которой пользователь может ввести полное или частичное название компании для поиска данных об этом.
Вот инструкция PDO, которую я использую для выполнения поиска в базе данных:
SELECT CompName FROM CompanyName WHERE CompName REGEXP :name ORDER BY CompName ASC LIMIT 1
Итак, я могу подготовить, связать, какие типы пользователей в поле поиска ввести имя параметра и выполнить оператор. Пока пользователь не вводит никаких метасимволов, он работает. Вот основное регулярное выражение, которое я вставляю в инструкцию PDO вместо имени:
^ whatusertyped – изначально я ищу полное совпадение. Поскольку некоторые названия компаний содержат периоды, я хочу, чтобы пользователь мог набирать эти символы и мое регулярное выражение, чтобы воспринимать их как литералы, а не метасимволы. До сих пор это то, как я заменяю метасимволы, чтобы получить их буквальное значение:
типы пользователей: C. искать название компании, которое начинается с C.
php вставляет ^ и \\\\, чтобы получить выход из ^ C \\.
mysql получает: ^ C \\. и ищет C. в начале названия компании, где период является буквальным и не означает «искать символ дикой карты».
Поэтому я пытаюсь использовать C., потому что в базе данных есть компания, чье имя начинается, и я должен получить соответствие, но я этого не делаю, оператор PDO возвращает обратно пустой массив.
Я попробовал запрос:
SELECT CompName FROM CompanyName WHERE CompName REGEXP "^C\\\\." ORDER BY CompName ASC LIMIT 1
непосредственно в mysql и вернул совпадение, и я также непосредственно выполнил запрос в PHP без подготовки, привязки и возврата спички. Мне кажется, проблема заключается в подготовке и привязке поискового термина к параметру, но я не смог понять, что именно и как его решить. Я действительно хочу использовать bind и готовить, как я сказал, чтобы избежать инъекции sql.
Любая помощь будет принята с благодарностью. Надеюсь, я четко объяснил проблему.
Я считаю, что значение, которое вы связываете с :name
должно быть просто ^C\.
, а не ^C\\.
, Вам не нужно выполнять экранирование для уровня sql , только для уровня регулярного выражения (т. Е. \.
Для литерала).
Также рассмотрите использование WHERE CompName LIKE 'C.%'
. Здесь вам не нужно регулярное выражение. Вы бы использовали так:
function like_escape($s) { // Do like-expression escaping return addcslashes($s, '%_'); } $searchprefix = 'C.'; $sql = 'SELECT CompName FROM CompanyName WHERE CompName LIKE ? ORDER BY CompName ASC'; $stmt = $db->prepare($sql); $likeclause = like_escape($searchprefix).'%'; $db->bindValue(1, $likeclause, PDO::PARAM_STR); $stmt->execute();