Работа с базой данных в WordPress. Объект $wpdb

Перед вами подробное руководство по построению запросов к базе данных WordPress при помощи объекта $wpdb класса wpdb.

Класс позволяет взаимодействовать с базой данных без построения SQL-запросов на чистом PHP.

Используем глобальный объект $wpdb

При использовании объекта $wpdb для построения SQL-запросов, нам следует определить его как глобальную переменную.

Например:

global $wpdb;
$results = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}options WHERE option_id = 1", OBJECT );

Этот пример позволяет получить опцию из таблицы wp_options со значением колонки option_id равным единице. Если мы сделаем print_r( $results ), то получим:

Array
(
    [0] => stdClass Object
        (
            [option_id] => 1
            [option_name] => siteurl
            [option_value] => https://misha.agency
            [autoload] => yes
        )
 
)

$wpdb-prepare() или как защититься от SQL-инъекций

Любые данные, которые вы передаёте в свои SQL-запрсоы должны очищаться, иначе вы повышаете риск SQL-инъекций для вашего сайта. Метод prepare отлично с этим справляется, он также поддерживает синтаксис sprintf() и vsprintf().

Понять принцип его работы лучше всего на примере.

$meta_key   = 'seo_title';
$meta_value = 'Привет, мир!';
 
$wpdb->query(
	$wpdb->prepare(
		"
		INSERT INTO $wpdb->postmeta
		( post_id, meta_key, meta_value )
		VALUES ( %d, %s, %s )
		",
		10,
		$meta_key,
		$meta_value
	)
);

Давайте разберём этот пример:

  • $wpdb->prepare() подготовливает SQL-запрос для $wpdb->query() и находится непосредственно внутри него.
  • Тут используется синтаксис sprintf(), в первом параметре у нас находится SQL-запрос INSERT INTO в виде строки, в котором переменные заменены на плейсхолдеры (%d и %s), которые будут заменены на переменные из следующих параметров в том же порядке, в котором они указаны. Например %d будет заменён на 10.
  • %d означает целое число, %s означает строку, больше значений можете найти в документации функции sprintf().

Синтаксис vsprintf() отличается тем, что значения передаются в запрос не бесконечным количеством переменных, а массивом.

$meta_key   = 'seo_title';
$meta_value = 'Привет, мир!';
 
$wpdb->query(
	$wpdb->prepare(
		"
		INSERT INTO $wpdb->postmeta
		( post_id, meta_key, meta_value )
		VALUES ( %d, %s, %s )
		",
		array(
			10,
			$meta_key,
			$meta_value,
		)
	)
);

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

Обязательно используйте $wpdb->prepare() с $wpdb->query(), $wpdb->get_col(), $wpdb->get_var(), $wpdb->get_row(), $wpdb->get_results().

Не нужно использовать $wpdb->prepare() с методами $wpdb->insert(), $wpdb->update(), $wpdb->replace(), $wpdb->delete(), так как он и так уже находится внутри них.

Для того, чтобы вам было легче разобраться, в последующих примерах я уже сразу буду добавлять $wpdb->prepare() там, где нужно!

Обращение к таблицам MySQL, префикс таблиц

Обратиться к стандартным таблицам в базе WordPress очень легко — ведь для этого предназначены переменные класса:

  • $commentmeta
  • $comments
  • $links
  • $options
  • $postmeta
  • $posts
  • $terms
  • $term_relationships
  • $term_taxonomy
  • $usermeta
  • $users

Как это будет выглядеть на деле:

$wpdb->query( 
	$wpdb->prepare(
		"
		DELETE FROM $wpdb->posts
		WHERE id = '%d'
		",
		$post_id
	)
);

Ок, а как быть с таблицами плагинов, или теми, которые сами мы и создали?

$wpdb->query( 
	$wpdb->prepare(
		"
		DELETE FROM " . $wpdb->prefix . "posts
		WHERE id = '%d'
		",
		$post_id
	)
);

$wpdb->get_results()

Первый метод больше всего похож на обычный запрос SELECT.

$wpdb->get_results( 'query', output_type );
output_type
Тип вывода данных.
  • OBJECT – объект (по умолчанию)
  • OBJECT_K – Ассоциативный массив, в котором в качестве ключей будут использоваться значения в первой колонке, дубликаты будут проигнорированы.
  • ARRAY_A – Нумерованный массив состоящий из ассоциативных массивов, в качестве индексов которых будут использоваться названия колонок.
  • ARRAY_N – Нумерованный двумерный массив.

Выводим заголовки всех опубликованных страниц:

$pages = $wpdb->get_results( 
	"
	SELECT post_title, post_content 
	FROM $wpdb->posts
	WHERE post_status = 'publish' 
	AND post_type = 'page'
	"
);
 
//вытаскиваем из базы данных заголовки и содержимое всех опубликованных страниц
if( $pages ) {
	foreach ( $pages as $page ) {
		echo $page->post_title;
	}
}
// выводим заголовки

Пример с использованием функции setup_postdata, то есть в итоге получается некий аналог WP_Query().

// В случае если на блоге есть опубликованные страницы, выводим заголовки со ссылками
$pages = $wpdb->get_results( 
	"
	SELECT * 
	FROM $wpdb->posts
	WHERE post_status = 'publish' 
	AND post_type = 'page'
	"
);
if ( $pages ) {
	foreach ( $pages as $post ) {
		setup_postdata( $post );
		echo '<h2><a href="' . get_permalink() . '">' . get_the_title() . '</a></h2>';
	}
} else {
	echo '<p>Ничего не найдено</p>';
}

$wpdb->get_var()

Переходим ко второму методу, get_var(), в отличие от get_results(), он позволяет вывести одно значение, причем это может быть сумма значений или количество строк.

$wpdb->get_var( 'query', column_offset, row_offset );
column_offset
(целое) номер по порядку нужной колонки (по умолчанию 0)
row_offset
(целое) номер по порядку нужного ряда (по умолчанию 0)

Выводим дату регистрации какого-то конкретного пользователя:

// узнаем и выводим дату регистрации пользователя с логином truemisha
$date = $wpdb->get_var(
	"
	SELECT user_registered
	FROM $wpdb->users
	WHERE user_login = 'truemisha'
	"
);
echo $date;

Пришло время узнать количество зарегистрированных пользователей на нашем сайте на WordPress:

$number_of_users = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->users" );
 
echo "Всего на сайте зарегалось {$number_of_users} человек.";

Подсчитаем сумму чего-нибудь из метаданных пользователя:

$amount = $wpdb->get_var( 
	$wpdb->prepare( 
		"
			SELECT sum(meta_value) 
			FROM $wpdb->usermeta 
			WHERE meta_key = %s
		", 
		$meta_key
	)
);
echo "Сумма равна {$amount}";

$wpdb->get_row()

Получает значения только из одной строки, удовлетворяющей условию.

$wpdb->get_row( 'query', output_type, row_offset );
output_type
Тип вывода данных,
  • OBJECT — объект (по умолчанию),
  • ARRAY_A — ассоциативный массив,
  • ARRAY_N — нумерованный массив;
row_offset
(целое) номер по порядку нужного ряда (по умолчанию 0)

Выводим заголовок поста с самым большим количеством комментариев:

$post = $wpdb->get_row(
	"
	SELECT post_title, post_content
	FROM $wpdb->posts
	WHERE post_status = 'publish'
	ORDER BY comment_count DESC LIMIT 0,1
	"
);
echo $post->title;

Используем для тех же целей ассоциативный массив:

$post = $wpdb->get_row(
	"
	SELECT post_title, post_content
	FROM $wpdb->posts
	WHERE post_status = 'publish'
	ORDER BY comment_count DESC LIMIT 0,1
	",
	ARRAY_A
);
echo $post[ 'title' ];

$wpdb->get_col()

Вывод данных только из одной колонки, в результате получаем одномерный объект.

$wpdb->get_col( 'query', column_offset );
column_offset
(целое) номер по порядку нужной колонки (по умолчанию 0)

Выводим заголовок самой первой опубликованной страницы:

$posts = $wpdb->get_col(
	"
	SELECT post_title
	FROM $wpdb->posts
	WHERE post_status = 'publish'
	AND post_type='page'
	"
);
echo $posts[0];

$wpdb->insert()

Предназначен для вставки строки в таблицу. Сразу перейду к примеру, потому что в синтаксисе на первый взгляд будет мало чего понятно.

$wpdb->insert( 
	$wpdb->prefix . 'usermeta', // указываем таблицу
	array( // 'название_колонки' => 'значение'
		'user_id' => 1,
		'meta_key' => 'first_name', 
		'meta_value' => 'Михаил' 
	), 
	array( 
		'%d', // %d - значит число
		'%s', // %s - значит строка
		'%s'
	) 
);
вставка строки в MySql таблицу INSERT

$wpdb->update()

Предположим в прошлом примере мы всё-таки создали строку и сейчас хотим её обновить:

$wpdb->update( 
	$wpdb->prefix . 'usermeta', // указываем таблицу
	array('meta_value' => 'Миша'), // поменяем имя 
	array( // где 
		'user_id' => 1,
		'meta_key' => 'first_name'
	), 
	array( '%s' ),
	array( // формат для «где»
		'%d',
		'%s'
	)
);
UPDADE - обновление строки в таблице MySql

Миша

Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школах Epic Skills и LoftSchool.

Если вам нужна помощь с сайтом или разработка с нуля на WordPress / WooCommerce — пишите. Я и моя команда будем рады вам помочь!

Комментарии — 42

Комментирование этого поста более не доступно.