Почему подготовленное Mysqli заявление не экранирует подстановочные знаки (% и _) и обратную косую черту ( \)?

В качестве меры безопасности я использую подготовленное Mysqli заявление и bindvariables.

Мой код показан ниже:

$what = trim($_GET['what']);
$key_word = "%".$what."%";  
$where_clause = " WHERE chair.company LIKE ? OR chair.business_category LIKE ? OR chair.summary LIKE ?";
$query = "SELECT chair.id_user, chair.company   FROM chair" . $where_clause; 
$con = @mysqli_connect($hostname,$username,$password, $database_name);
$stmt = mysqli_prepare($con, $query);
$bind = mysqli_stmt_bind_param($stmt, 'sss', $key_word, $key_word, $key_word);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
$bind = mysqli_stmt_bind_result($stmt,$business_id,$company);
while (mysqli_stmt_fetch($stmt))
    {
    echo htmlspecialchars($company)."<br>";
    }

Из документации:

В качестве альтернативы явному экранированию специальных символов многие MySQL API предоставляют возможность заполнителя, которая позволяет вставлять специальные маркеры в строку оператора, а затем привязывать к ним значения данных при выполнении оператора. В этом случае API заботится о экранировании специальных символов в значениях для вас.

Я могу использовать все символы на клавиатуре (за исключением \ % _) и экранироваться и соответствовать правильно. Моя проблема заключается в том, что этот подготовленный оператор не экранирует подстановочные знаки (% и _) и экранирующий символ (\). Когда я ищу% Он перечисляет все элементы в базе данных. И когда я ищу _ Он перечисляет все элементы. И при поиске (\), он не соответствует желаемому элементу.

Я нашел похожий Вопрос, но ответчик никогда не отвечал моему требованию, потому что мне нужно использовать подстановочный знак в моем запросе.

Другой ответ на вопрос говорит, что чтобы избежать их, используйте двойную обратную косую черту

Даже это не проблема безопасности, почему готовое заявление не ускользает от них? Есть ли какая-либо ошибка в том, как я использую это в своем коде? Как динамически избежать их? Какую функцию я могу использовать для этого?

1 ответ

Решение

Подготовленные заявления избегают \ должным образом. В противном случае они не будут создавать правильно отформатированные строковые литералы, что является основной целью подготовленных операторов.

Кроме того, % а также _ только специальные символы LIKE Сравнение, но не для строк в целом. Таким образом, нет необходимости избегать их вообще. Если вам нужно сбежать от них для LIKE Для сравнения сделайте это явно:

$what = addcslashes($what, '%_');

Кроме того, LIKE также поддерживает использование escape-символа, кроме \:

mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|';
        -> 1
Другие вопросы по тегам