wpdb::prepare() publicWP 2.3.0

Дозволяє писати 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 ] ).

Приклади

0

#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'
);
0

#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
  )
);
0

#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.0Formalizated existing and already documented …$args parameter by updating the function signature. The second parameter був змінений від $args to …$args .