wpdb::prepare()
Дозволяє писати SQL запит з очищенням параметрів, що передаються в нього.
У рядку запиту замість параметра, що передається, потрібно використовувати плейсхолдер:
%d
(integer)%f
(float)%s
(string)
Також для кожного з плейсхолдерів вказується PHP змінна, яка замінить плейсхолдер. При заміні змінна буде очищена . Синтаксис схожий на sprintf() .
З WP 3.5 обов’язково повинні бути передані щонайменше 2 параметри: запит і значення змінної, інакше буде php помилка (User Notice).
-
Лапки для плейсхолдерів
%s
та'%s'
. Плейсхолдери можуть бути в лапках або без них:
WHERE field = %s
абоWHERE field = '%s'
. Лапки прийнято не ставити.echo $wpdb->prepare( "foo = %s", 'a'); // foo = 'a' echo $wpdb->prepare( "foo = '%s'", 'a' ); // foo = 'a'
- Параметр кожного плейсхолдера.
Параметр має бути вказаний для кожного плейсхолдера.
echo $wpdb->prepare( 'foo = %s AND bar = %s', 'a' ); echo $wpdb->prepare( 'foo = %1$s AND bar = %1$s', 'a' ); // В обох випадках побачимо помилку: // User Notice: wpdb::prepare був названий incorrectly. // The query does no contain the correct number of placeholders (2) // for number of arguments passed (1).
-
Порядкові плейсхолдери
%1$s
. Для сумісності зі старими версіями: порядкові плейсхолдери (наприклад,
%1$s
,%5s
) обробляються інакше – їм не додаються лапки, тому вони мають бути забезпечені правильними лапками у рядку запиту.echo $wpdb->prepare( 'foo = %1$s', 'a"a' ); // foo = a"a echo $wpdb->prepare( 'foo = "%1$s"', 'a"a' ); // foo = "a"a" echo $wpdb->prepare( 'foo = %1s', 'a"a' ); // foo = a"a echo $wpdb->prepare( 'foo = %s', 'a"a' ); // foo = 'a"a'
-
Знак
%
Знак
%
у рядку запиту, який не відноситься до плейсхолдеру, потрібно записувати так%%
.echo $wpdb->prepare( "%foo AND id = %d", 2 ); // User Notice: wpdb::prepare був названий incorrectly. echo $wpdb->prepare( "%%foo AND id = %d", 2 ); // %foo AND id = 2
-
%
у LIKE синтаксисі Підстановочні знаки відсотка
%
в LIKE синтаксисі повинні вказуватися через параметр підстановки, що містить повний LIKE рядок, а не безпосередньо у запиті. Також дивіться wpdb::esc_like() .$like = '%'. $wpdb->esc_like( "bar's" ) .'%end'; echo $wpdb->prepare( "foo LIKE %s", $like ); // foo LIKE '{a0d1d}bar's{a0d1d}end'
SQL ін’єкція
У SQL є таке поняття як ін’єкція (впровадження в запит SQL коду). Зробити його можна, коли на запит передаються динамічні дані. Наприклад, у запит передається значення input поля, це поле можна вказати дані, які у результаті стануть частиною SQL запиту. Так можна запропонувати запит і щось зіпсувати або просто порушити код самого запиту. Виглядає це так:
$sql = "SELECT * FROM table WHERE id = '$var'";
Тепер, якщо var = 2' AND id = (DROP TABLE table2)
то в результаті запит вийти такий:
SELECT * FROM table WHERE id = '2' AND id = (DROP TABLE table2)
Таким чином, можна впровадитися в сам запит і змінити його. Щоб цього не відбулося запити з перемінними, що передаються в них, потрібно обробляти методом prepare() :
$sql = $wpdb->prepare( "SELECT * FROM table WHERE id = %s", $var);
esc_sql()
Крім методу $wpdb->prepare(), запит можна очистити функцією esc_sql() . Але «prepare» краще, тому що виправляє деякі помилки форматування.
$name = esc_sql($name); $status = esc_sql($status); $wpdb->get_var( "SELECT something FROM table WHERE foo = '$name' and status = '$status'" );
ВАЖЛИВО! Після esc_sql() очищений рядок можна використовувати тільки всередині лапок ''
або ""
. Тобто. правильно писати field = '$value'
, а не field = $value
де$value = esc_sql( $value );
{} Це метод класу: wpdb{}
wpdb::add_placeholder_escape()
Хуків немає.
Повертає
Строку|null
. Sanitized query string, якщо це є query to prepare.
Використання
Global $wpdb; $wpdb->prepare( $query, ...$args );
-
$query
(рядок) (обов’язковий) Рядок запиту. У ньому можна використовувати замінники:
%d
– Число%s
– Рядок%f
– Дробове число (число з плаваючою точкою, з версії 3.3).
-
…$args
(рядок/число/масив) Змінні, які будуть використані для заміни плейсхолдерів
%s %d %f
у рядку запиту.Ці змінні можна вказати через кому (як додаткові параметри функції) або в масиві:
$wpdb->prepare( 'query', $param1, $param2 )
$wpdb->prepare( 'query', [ $param1, $param2 ] )
.
Приклади
#1 Демонстрація роботи
$wpdb->prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d OR `other_field` LIKE %s", [ 'foo', 1337, '% bar'] ); $wpdb->prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' );
#2 Додамо довільне поле до поста 10
З прикладу видно, що з prepare() немає необхідності дбати про екранування лапок та інше, що може зашкодити запиту.
$metakey = " крах " БД " ; $metavalue = "WordPress може 'зламати' Базу Даних якщо не екранувати запит."; $wpdb->query( $wpdb->prepare( "INSERT INTO $wpdb->postmeta ( post_id, meta_key, meta_value ) VALUES ( %d, %s, %s )", 10, $metakey, $metavalue ) );
#3 Передача параметрів у вигляді масиву
Це такий самий приклад, тільки тут всі змінні передаються у другому параметрі як масиву.
Передавати параметри у вигляді масиву може бути корисно, коли ми заздалегідь не знаємо кількість аргументів, які потрібно буде передати.
$metakey = " крах " БД " ; $metavalue = "WordPress може 'зламати' Базу Даних якщо не екранувати запит."; $wpdb->query( $wpdb->prepare( "INSERT INTO $wpdb->postmeta ( post_id, meta_key, meta_value ) VALUES ( %d, %s, %s )", array( 10, $metakey, $metavalue ) ) );
список змін
З версії 2.3.0 | Введено. |
З версії 5.3.0 | Formalizated existing and already documented …$args parameter by updating the function signature. The second parameter був змінений від $args to …$args . |