Перед вами подробное руководство по построению запросов к базе данных 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 ) );
Давайте разберём этот пример:
Синтаксис 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 очень легко — ведь для этого предназначены переменные класса:
Как это будет выглядеть на деле:
$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 );
Выводим заголовок самой первой опубликованной страницы:
$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' ) );
$wpdb->update()
Предположим в прошлом примере мы всё-таки создали строку и сейчас хотим её обновить:
$wpdb->update( $wpdb->prefix . 'usermeta', // указываем таблицу array('meta_value' => 'Миша'), // поменяем имя array( // где 'user_id' => 1, 'meta_key' => 'first_name' ), array( '%s' ), array( // формат для «где» '%d', '%s' ) );