Как правильно подготовить SQL-запрос с оператором %LIKE%?
Я хочу использовать оператор LIKE %text%, при этом используя класс WordPress $wpdb для санитизации и подготовки входных данных.
SELECT column_1 from `prefix_my_table` WHERE column_2 LIKE '%something%';
Я пробовал что-то вроде этого, но безуспешно:
$wpdb->prepare( "SELECT column_1 from `{$wpdb->base_prefix}my_table` WHERE column_2 LIKE %s;", like_escape($number_to_put_in_like));
Как правильно подготовить SQL-запрос с оператором %LIKE%, используя класс базы данных WordPress?
Функция $wpdb->esc_like
существует в WordPress потому, что обычное экранирование базы данных не экранирует символы %
и _
. Это означает, что вы можете добавлять их в свои аргументы для wpdb::prepare()
без проблем. Это также то, что я вижу в основном коде WordPress:
$wpdb->prepare(" AND $wpdb->usermeta.meta_key = '{$wpdb->prefix}capabilities' AND $wpdb->usermeta.meta_value LIKE %s", '%' . $this->role . '%');
Таким образом, ваш код будет выглядеть так:
$wpdb->prepare(
"SELECT
column_1
FROM
`{$wpdb->base_prefix}my_table`
WHERE
column_2 LIKE %s;",
'%' . $wpdb->esc_like($number_to_put_in_like) . '%'
);
Вы также можете добавить %%
в свой запрос, чтобы получить буквальный символ %
(wpdb::prepare()
использует vsprintf()
в фоновом режиме, который имеет такой синтаксис), но помните, что ваша строка не будет заключена в кавычки, вам нужно добавить их самостоятельно (что обычно не требуется делать в wpdb::prepare()
).

@FranciscoCorralesMorales: Чтобы указать, что всё внутри должно рассматриваться как выражение с переменной, иначе будет виден только $wpdb
, а ->prefix
после него будет проигнорирован.

@JanFabry Близко. Я бы уточнил комментарий: "... иначе будет воспринято всё выражение $wpdb->base_prefixmy_table
и будет попытка найти свойство base_prefixmy_table
вместо просто base_prefix
.

Также стоит упомянуть, что символы % заменяются на невероятно длинный хэш. Это действительно выглядит странно, когда вы делаете var_dump SQL-вывода. После нескольких часов поисков удалось выяснить, что это исправление уязвимости SQL-инъекций в WordPress 4.8.3. https://stackoverflow.com/a/57914094/7977916

Вам нужно удваивать знаки процента, чтобы они не интерпретировались как маркеры фрагментов в wpdb->prepare()
:
$wpdb->prepare( "SELECT column_1 from `{$wpdb->base_prefix}my_table` WHERE column_2 LIKE %%%s%%;", $wpdb->esc_like( $number_to_put_in_like));
P.S. Не уверен, что это лучший/единственный способ сделать это.

Помните, что вы должны сами добавить кавычки вокруг строки, потому что wpdb::prepare
добавляет их только для %s
, перед которым нет символа %
. Финальная часть вашего запроса должна выглядеть как WHERE column_2 LIKE '%%%s%%'
.

Вот один из проверенных способов, который работает:
$search_text = "%" . $_GET['some_text'] . "%";
$user_count = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM mix_library WHERE ml_setting_name LIKE %s",
$search_text
)
);
Замените переменные в соответствии с вашими потребностями.

Вам следует экранировать символы %
(используя функцию like_escape()
). Подробнее см.: http://codex.wordpress.org/Class_Reference/wpdb#Protect_Queries_Against_SQL_Injection_Attacks

$safe_sql = $wpdb->prepare("SELECT * FROM $wp_track_table $sql",["*yoursecretkey*".$_POST['search']."*yoursecretkey*"]);
$safe_sql = str_replace("*yoursecretkey*", "%", $safe_sql);
Я нашел подходящее решение с приведенным выше кодом. Обязательно попробуйте его.

То есть ваш подход заключается в том, чтобы передать случайную строку в prepare(), а затем заменить её на проценты? Это похоже на борьбу с WordPress.
