Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

База данных и $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_ вручную: на сайте с другой приставкой запрос перестанет работать.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.