Це докладний посібник про те, як створювати запити до бази даних WordPress за допомогою об’єкта $wpdb класу wpdb.

Цей клас дає змогу працювати з базою даних, не використовуючи чистий SQL у коді PHP.

Використання глобального об'єкта $wpdb

Щоб створювати SQL-запити через $wpdb, потрібно оголосити його як глобальну змінну.

Приклад:

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://testsite.com
            [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(), адже він уже вбудований у них.

Звернення до таблиць 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
	)
);

Цей код демонструє, як виконати запит до таблиці posts для видалення запису за його ID. Завдяки змінним класу ти можеш легко звертатися до потрібних таблиць, навіть якщо префікс таблиць змінений.

Як бути з таблицями плагінів чи власноруч створеними таблицями?

Для доступу до таблиць, створених плагінами або власноруч, ти можеш використовувати префікс таблиць WordPress через властивість $wpdb->prefix. Це дозволяє врахувати можливий нестандартний префікс бази даних.

Наприклад:

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

Що тут відбувається:

  • $wpdb->prefix повертає поточний префікс таблиць (наприклад, wp_), гарантуючи, що запит буде коректно виконаний навіть із кастомним префіксом.
  • Таким способом ти можеш звертатися до будь-яких таблиць, створених плагінами чи вручну.

Пам’ятай, що використання prepare() допомагає уникнути SQL-ін’єкцій, навіть із власними таблицями.

$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;  
	}  
}  
// Виводимо заголовки

У цьому коді ми отримуємо всі записи з таблиці posts, які є опублікованими сторінками (post_status = 'publish' та post_type = 'page'). Результат за замовчуванням повертається у вигляді об’єктів, до яких можна звертатися через властивості ($page->post_title).

Приклад із використанням функції setup_postdata, як аналог WP_Query()

Цей підхід дозволяє працювати з результатами SQL-запиту так, ніби це об’єкти WP_Post.

// Якщо на сайті є опубліковані сторінки, виводимо заголовки з посиланнями  
$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>';  
	}  
	// Завжди скидай дані після використання setup_postdata  
	wp_reset_postdata();  
} else {  
	echo '<p>Нічого не знайдено</p>';  
}  

Що відбувається у коді:

  1. Запит отримує всі записи з таблиці posts, які є опублікованими сторінками (post_status = 'publish' та post_type = 'page').
  2. У циклі кожен результат обробляється функцією setup_postdata, що дозволяє використовувати стандартні функції WordPress, наприклад, get_permalink() та get_the_title().
  3. Після обробки результатів завжди викликай wp_reset_postdata(), щоб уникнути конфліктів із глобальним об’єктом $post.

Цей підхід зручний, коли потрібно зберігати гнучкість WP_Query(), але працювати з власними SQL-запитами.

$wpdb->get_var()

Цей метод відрізняється від get_results(), оскільки дозволяє отримати лише одне значення. Це може бути, наприклад, сума значень або кількість рядків у запиті.

$wpdb->get_var( 'query', column_offset, row_offset );

Аргументи:

  • column_offset
    (ціле число) Порядковий номер потрібної колонки. За замовчуванням — 0.
  • row_offset
    (ціле число) Порядковий номер потрібного рядка. За замовчуванням — 0.

Приклад:

// Отримуємо кількість опублікованих сторінок  
$total_pages = $wpdb->get_var(  
	"  
	SELECT COUNT(*)  
	FROM $wpdb->posts  
	WHERE post_status = 'publish'  
	AND post_type = 'page'  
	"  
);  

if ( $total_pages ) {  
	echo "Кількість опублікованих сторінок: $total_pages";  
} else {  
	echo "Опублікованих сторінок не знайдено.";  
}  

Що відбувається у прикладі:

  • get_var() виконує SQL-запит і повертає лише одне значення — у цьому випадку кількість рядків, що відповідають умові.
  • Це ефективно для запитів, де потрібен лише один результат, наприклад, підрахунок записів або отримання певного значення.

Цей метод добре підходить для економії ресурсів, коли повний набір даних не потрібен.

Приклад 1: Виведення дати реєстрації конкретного користувача

// Дізнаємося та виводимо дату реєстрації користувача з логіном testuser  
$date = $wpdb->get_var(  
	"  
	SELECT user_registered  
	FROM $wpdb->users  
	WHERE user_login = 'testuser'  
	"  
);  
echo $date;  

Приклад 2: Підрахунок кількості зареєстрованих користувачів на сайті

$number_of_users = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->users" );  

echo "Всього на сайті зареєстровано {$number_of_users} користувачів.";  

Приклад 3: Підрахунок суми значень з метаданих користувачів

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

Пояснення:

  • У першому прикладі ми отримуємо дату реєстрації користувача з певним логіном за допомогою get_var().
  • У другому прикладі обчислюється кількість усіх користувачів, зареєстрованих на сайті.
  • У третьому прикладі ми підраховуємо суму значень метаданих певного користувача, використовуючи sum() для збережених значень у таблиці usermeta.

Цей підхід корисний для вибірки одиничних значень із бази даних, коли потрібен лише один результат, наприклад, сума або кількість записів.

$wpdb->get_row()

Цей метод дозволяє отримати значення лише з одного рядка, який задовольняє умови запиту.

$wpdb->get_row( 'query', output_type, row_offset );

Аргументи:

  • output_type
    Тип виведення даних:
    • OBJECT — повертається об'єкт (за замовчуванням);
    • ARRAY_A — асоціативний масив;
    • ARRAY_N — нумерований масив.
  • row_offset
    (ціле число) Порядковий номер потрібного рядка. За замовчуванням — 0.

Приклад 1: Виведення заголовка поста з найбільшою кількістю коментарів (як об'єкт):

$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->post_title;

Приклад 2: Виведення того ж результату, але у вигляді асоціативного масиву:

$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['post_title'];

Пояснення:

  • В першому прикладі використовуємо OBJECT для отримання результату у вигляді об'єкта, з якого можна отримати значення через ->.
  • В другому прикладі дані повертаються як асоціативний масив, де значення доступні за індексами, наприклад, $post['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];

Пояснення:

  • У цьому прикладі ми отримуємо заголовки всіх опублікованих сторінок за допомогою get_col(), який повертає одномірний масив значень (заголовків).
  • Оскільки результат — масив, доступ до значень здійснюється за індексом, у нашому випадку це 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'  // %s — означає рядок
	) 
);

Пояснення:

  • Перший параметр — це назва таблиці. Тут використовується $wpdb->prefix, щоб врахувати префікс таблиць WordPress, що дозволяє забезпечити сумісність на різних сайтах.
  • Другий параметр — це асоціативний масив, де вказуються назви колонок і відповідні їм значення, які необхідно вставити.
  • Третій параметр — це масив форматів для кожного значення.
    • %d — для цілих чисел (integer);
    • %s — для рядків (string).

Цей метод дозволяє безпечно вставляти дані в таблицю, гарантуючи, що всі значення будуть оброблені належним чином, щоб уникнути SQL-ін'єкцій.

$wpdb->update()

Припустимо, в попередньому прикладі ми вже створили запис і тепер хочемо оновити його.

$wpdb->update( 
	$wpdb->prefix . 'usermeta', // вказуємо таблицю
	array('meta_value' => 'Анатолій'), // змінюємо ім'я
	array( // умови для оновлення
		'user_id' => 1,
		'meta_key' => 'first_name'
	), 
	array( '%s' ), // формат для значень, які будемо оновлювати
	array( // формат для умов
		'%d',
		'%s'
	)
);

Пояснення:

  • Перший параметр — це назва таблиці, в якій ми хочемо оновити дані.
  • Другий параметр — це асоціативний масив, де вказуємо назву колонки, яку потрібно змінити, і нове значення (в нашому випадку змінюється значення в колонці meta_value на "Анатолій").
  • Третій параметр — це масив умов, за якими відбуватиметься пошук рядка для оновлення (у нашому випадку шукаємо рядок, де user_id дорівнює 1 і meta_key дорівнює 'first_name').
  • Четвертий параметр — це масив форматів для нових значень.
  • П'ятий параметр — це масив форматів для умов пошуку, де %d позначає ціле число, а %s — рядок.

Цей метод дозволяє безпечно оновлювати дані в таблиці, зберігаючи належну обробку значень, щоб уникнути помилок та SQL-ін'єкцій.

Висновок

Робота з базою даних у WordPress через об'єкт $wpdb дозволяє ефективно взаємодіяти з даними без необхідності писати складні SQL-запити вручну. Методи класу wpdb, такі як get_results(), get_var(), get_row(), get_col(), insert(), update() та інші, дають змогу легко виконувати необхідні операції з базою даних.

Ключовим аспектом є використання методу $wpdb->prepare(), який захищає від SQL-ін'єкцій і робить роботу з базою даних безпечною. Завдяки цьому методу можна використовувати плейсхолдери для заміни значень у запитах, що автоматично очищує дані від небезпечних символів.

Методи $wpdb дозволяють працювати з різними типами даних (масиви, об'єкти, рядки) та забезпечують гнучкість у виборі результатів. Це допомагає значно спростити роботу з базою даних у WordPress, знизити ймовірність помилок і підвищити безпеку.

Загалом, ці інструменти роблять розробку з базою даних на WordPress потужною, ефективною та безпечною.