База данных и $wpdb
Обычно с базой данных в WordPress работают через готовые функции: get_posts(), get_post_meta(), get_option(). Но для отчётов, сложных выборок и собственных таблиц нужен прямой доступ — объект $wpdb.
Таблицы WordPress
| Таблица | Что хранит |
|---|---|
wp_posts | Записи, страницы, вложения и свои типы записей |
wp_postmeta | Произвольные поля записей |
wp_users, wp_usermeta | Пользователи и их данные |
wp_options | Настройки сайта |
wp_terms, wp_term_taxonomy, wp_term_relationships | Рубрики, метки и их связи с записями |
wp_comments, wp_commentmeta | Комментарии |
Приставка wp_ может быть другой — её задают при установке.
Чтение
global $wpdb;
$count = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_status = 'publish'");
$rows = $wpdb->get_results("SELECT ID, post_title FROM {$wpdb->posts} ORDER BY post_date DESC LIMIT 5");
foreach ($rows as $row) {
echo esc_html($row->post_title);
}| Метод | Что возвращает |
|---|---|
get_var() | Одно значение |
get_row() | Одну строку |
get_col() | Один столбец массивом |
get_results() | Все строки |
Имена таблиц берут из свойств $wpdb->posts, $wpdb->users — в них уже есть правильная приставка.
Подготовленные запросы
Значения, пришедшие извне, вставляют только через prepare():
global $wpdb;
$authorId = absint($_GET['author'] ?? 0);
$titles = $wpdb->get_col(
$wpdb->prepare(
"SELECT post_title FROM {$wpdb->posts} WHERE post_author = %d AND post_status = %s",
$authorId,
'publish',
)
);| Метка | Тип |
|---|---|
%d | Целое число |
%f | Дробное число |
%s | Строка |
%i | Имя таблицы или столбца |
Вставка, изменение, удаление
global $wpdb;
$table = $wpdb->prefix . 'book_reviews';
$wpdb->insert($table, ['book_id' => 15, 'rating' => 5, 'author' => 'Анна'], ['%d', '%d', '%s']);
$reviewId = $wpdb->insert_id;
$wpdb->update($table, ['rating' => 4], ['id' => $reviewId], ['%d'], ['%d']);
$wpdb->delete($table, ['id' => $reviewId], ['%d']);Эти методы сами экранируют значения. Третий аргумент — форматы столбцов.
Своя таблица
Таблицу создают при активации плагина функцией dbDelta():
// books.php
register_activation_hook(__FILE__, function () {
global $wpdb;
$table = $wpdb->prefix . 'book_reviews';
$charset = $wpdb->get_charset_collate();
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta("CREATE TABLE $table (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
book_id bigint(20) unsigned NOT NULL,
rating tinyint(1) NOT NULL,
author varchar(100) NOT NULL,
created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY book_id (book_id)
) $charset;");
});dbDelta() сравнивает описание с существующей таблицей и вносит только разницу. Она требовательна к записи: каждое поле на своей строке и два пробела после PRIMARY KEY.
Нужна ли своя таблица
Чаще всего — нет. Свой тип записей с произвольными полями даёт редактор, поиск, права и REST API без единого запроса SQL. Свою таблицу заводят, когда строк очень много или данные совсем не похожи на записи: журнал событий, оценки, статистика.
Частая ошибка
Запрос, в который значение вставлено напрямую, — "... WHERE post_author = $_GET[author]" — открывает путь SQL-инъекции. Всё, что пришло от посетителя, передавайте через $wpdb->prepare(). И не пишите имя таблицы с приставкой wp_ вручную: на сайте с другой приставкой запрос перестанет работать.