Как правильно подготовить SQL-запрос с оператором %LIKE%?

8 февр. 2011 г., 04:15:00
Просмотры: 63.7K
Голосов: 56

Я хочу использовать оператор 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?

0
Все ответы на вопрос 4
4
82

Функция $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()).

8 февр. 2011 г. 11:39:26
Комментарии

для чего нужны {} ?

Francisco Corrales Morales Francisco Corrales Morales
21 авг. 2014 г. 01:39:00

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

Jan Fabry Jan Fabry
21 авг. 2014 г. 18:14:14

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

Flimm Flimm
10 окт. 2017 г. 12:24:25

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

NME New Media Entertainment NME New Media Entertainment
4 янв. 2022 г. 22:26:17
3
10

Вам нужно удваивать знаки процента, чтобы они не интерпретировались как маркеры фрагментов в 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. Не уверен, что это лучший/единственный способ сделать это.

8 февр. 2011 г. 08:52:19
Комментарии

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

Jan Fabry Jan Fabry
8 февр. 2011 г. 11:39:08

Это отлично сработало вместе с советом от @JanFabry.

Gavin Gavin
31 окт. 2021 г. 12:32:26

Понравился этот ответ больше всего из-за использования esc_like и комментария @JanFabry.

Tami Tami
18 июн. 2022 г. 16:06:41
1

Вот один из проверенных способов, который работает:

$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 
    ) 
);

Замените переменные в соответствии с вашими потребностями.

25 окт. 2012 г. 08:02:20
Комментарии

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

Stephen Harris Stephen Harris
25 окт. 2012 г. 12:25:07
2
$safe_sql = $wpdb->prepare("SELECT * FROM $wp_track_table $sql",["*yoursecretkey*".$_POST['search']."*yoursecretkey*"]);

$safe_sql = str_replace("*yoursecretkey*", "%", $safe_sql);

Я нашел подходящее решение с приведенным выше кодом. Обязательно попробуйте его.

22 сент. 2022 г. 23:06:27
Комментарии

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

Rup Rup
23 сент. 2022 г. 14:46:17

По сути, шаблонизация, пожалуй. Не самый чистый способ, но определённо один из подходов! Спасибо.

editor editor
24 сент. 2022 г. 00:15:13