Працюємо з базою даних WordPress. Основи роботи з базою даних в WordPress, з допомогою класу wpdb

462

Від автора: в той час як ви вже застосовуєте багато функцій в WordPress для взаємодії з базою даних, що існує легкий і безпечний спосіб робити це безпосередньо з допомогою класу $wpdb. Заснований на чудовому класі ezSQL від Джастіна Вінсента (Justin Vincent), $wpdb дає вам можливість адресувати запити до будь-якої таблиці у своїй базі даних, а також допомагає вам оперувати повернутими даними. WPDB — це відмінний клас, для роботи з базою даних в WordPress.

Так як ця функціональність вбудована в WordPress не потрібно відкривати окреме з’єднання бази даних (в такому випадку ви будете дублювати код), і не потрібно виконувати хакі, такі як зміна результуючого безлічі після того, як до нього був виконаний запит.

Працюємо з базою даних WordPress. Основи роботи з базою даних в WordPress, з допомогою класу wpdb

Клас $wpdb моделює і автоматизує безліч завдань, пов’язаних з базою даних WordPress..

У цій статті я покажу вам, як почати роботу з класом $wpdb, як повертати дані зі своєї бази WordPress і як запускати більш просунуті запити, які оновлюють або видаляють що-небудь в базі даних. Прийоми, описані тут, приберуть деякі обмеження, на які ви натикаєтеся в таких функціях, як get_posts() і wp_list_categories(), дозволяючи вам перекроювати запити під ваші приватні потреби. Цей метод також може зробити ваш вебсайт більш ефективним, надаючи тільки ті дані, які потрібні — ні більше, ні менше, тепер ви будете працювати з базою даних WordPress по-дорослому.

Починаємо працювати з базою даних в WordPress

Якщо ви знаєте, як працює MySQL або подібні йому мови, то легко опануєте цим класом і вам доведеться мати на увазі тільки невелика кількість назв функцій. Основне застосування цього класу найкраще пояснюється на прикладі, так що давайте зробимо запит до бази даних і отримаємо ID і назви чотирьох останніх постів, відсортованих у порядку кількості коментарів (по спадній).

get_results(“SELECT ID, post_title FROM $wpdb->posts WHERE post_status = ‘publish’
AND post_type=’post’ ORDER BY comment_count DESC LIMIT 0,4”)

Як видно, це основний SQL-запит з обгорненим навколо нього деякою кількістю PHP. Клас $wpdb містить метод (метод – це спеціальна назва функцій, що знаходяться усередині класів) з назвою get_results(), який не тільки отримає ваші результати, але і покладе їх у відповідний об’єкт. Ви могли помітити, що замість застосування wp_posts для назви таблиці я використав $wpdb->posts, що допомагає отримати доступ до основних таблиць WordPress. Пізніше буде пояснено, навіщо це потрібно застосовувати.

Об’єкт $results тепер містить ваші дані в наступному форматі:

Array
(
[0] => stdClass Object
(
[ID] => 6
[post_title] => The Male Angler Fish Gets Completely Screwed
)
[1] => stdClass Object
(
[ID] => 25
[post_title] => 10 Truly Amazing Icon Sets From Germany
)
[2] => stdClass Object
(
[ID] => 37
[post_title] => Квіти Is Awesome
)
[3] => stdClass Object
(
[ID] => 60
[post_title] => Gathering Resources and Inspiration With Evernote
)
)

Витяг результатів з бази даних

Якщо ви хочете відшукати і вибрати якусь інформацію з бази даних WordPress, можете застосувати для структурування даних, одну з чотирьох функцій-асистентів.

get_results()

Це та функція, яку ми розглядали раніше. Вона підходить найкраще, коли вам потрібні двовимірні дані (безліч рядків і колонок). Вона перетворює дані в масив, що містить окремі об’єкти для кожного рядка.

get_results(“SELECT ID, post_title FROM wp_posts WHERE post_status = ‘future’
AND post_type=’post’ ORDER BY post_date ASC LIMIT 0,4”)
// Echo the title of the first post scheduled
echo $posts[0]->post_title;
?>

get_row

Коли вам потрібно знайти тільки одну окремий рядок у базі даних (наприклад, пост з найбільшою кількістю коментарів), можна використовувати get_row(). Він витягує дані в одновимірний об’єкт.

get_row(“SELECT ID, post_title FROM wp_posts WHERE post_status = ‘publish’
AND post_type=’post’ ORDER BY comment_count DESC LIMIT 0,1”)
// Echo the title of the most commented post
echo $posts->post_title;
?>

get_col

Цей метод багато в чому схожий на get_row(), але замість захоплення окремого рядка результатів він бере окрему колонку. Це корисно, якщо вам хотілося б повернути ID лише 10 найбільш обговорюваних постів. Як і get_row(), він зберігає результати в одновимірному об’єкті.

get_col(“SELECT ID FROM wp_posts WHERE post_status = ‘publish’
AND post_type=’post’ ORDER BY comment_count DESC LIMIT 0,10”)
// Echo the ID of the 4th most commented post
echo $posts[3]->ID;
?>

get_var

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

get_var(“SELECT user_email FROM wp_users WHERE user_login = ‘danielpataki’ “)
// Echo the user’s email address
echo $email;
?>

Вставка в базу даних

Щоб зробити вставку, можна використовувати метод insert:

$wpdb->insert( $table, $data, $format);

Цей метод приймає три аргумента. Перший визначає назву таблиці, в яку ви вставляєте дані. Другий аргумент – це масив, що містить колонки та їх відповідні значення як пар «ключ-значення» (key-value). Третій параметр визначає тип даних значень в тому порядку, які ви їм присвоїли. Ось приклад:

insert($wpdb->usermeta, array(“user_id” => 1, “meta_key” => “awesome_factor”, “meta_value” => 10), array(“%d”, %s, “%d”));
// Еквівалентно:
// INSERT INTO wp_usermeta (user_id, meta_key, meta_value) VALUES (1, “awesome_factor”, 10);
?>

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

Визначення формату – додаткова опція; всі значення за замовчуванням вважаються рядками, але включати його в метод – усталена практика. Три значення, які ви можете використовувати – це %s рядків, %d для десяткових чисел і %f для чисел з плаваючою точкою.

Оновлення даних

До цього моменту ви вже не здивуєтеся, коли почуєте, що для оновлення даних у нас також є метод-асистент з дуже сильним назвою update(). Його застосування нагадує те, що ми бачили вище; але для маніпулювання виразом where нашого оновлення потрібні два додаткових параметра.

$wpdb->update( $table, $data, $where, $format = null, $where_format = null );

Параметри $table, $data і $format повинні бути вам знайомі; вони все ті ж, що і раніше. Використовуючи параметр $where, ми можемо визначити умови оновлення. Це повинен бути масив у формі пар «колонка-значення» (column-value). Якщо ви визначаєте множинні параметри, то вони будуть об’єднані логікою AND. $where_format – такий же, як $format: він визначає формат значень в параметрі $where.

$wpdb->update( $wpdb->posts, array(“post_title” => “Modified Post Title”), array(“ID” => 5), array(“%s”), array(“%d”) );

Інші запити

У той час як представлені вище помічники просто відмінні, іноді необхідно виконання або інших більш складних запитів, ніж можуть дозволити асистенти. Якщо вам потрібно виконати оновлення зі складним реченням where, що містить множинне логіку AND/OR, то ви не зможете застосувати метод update(). Якщо вам потрібно зробити щось на зразок видалення рядка або установки набору характеристик з’єднання, то вам би знадобилося використовувати загальний метод query(), що дає можливість виконувати будь-який вид запитів.

$wpdb->query(“DELETE FROM wp_usermeta WHERE meta_key = ‘first_login’ OR meta_key = ‘security_key’ “);

Захист і валідація

Сподіваюся, вам не потрібно розповідати про те, як важливо переконатися, що ваші дані захищені і що вашою базою даних не зможуть маніпулювати! Валідація даних трохи виходить за межі цієї статті, але обов’язково подивіться коли-небудь, що може сказати Кодекс WordPress про Валідації даних (Data Validation).

Додатково до валідації вам знадобиться екранувати всі запити (escape). Навіть якщо ви не знайомі з атаками SQL-ін’єкції, все одно застосовуйте цей метод, а пізніше почитайте про нього, бо це дуже важливо.

Хороша новина: якщо ви застосовуєте будь-які функції-помічники, то вам не потрібно нічого робити: запит для вас вже екранований. Однак якщо ви застосовуєте метод query(), екранування вам доведеться вручну з допомогою методу prepare().

$sql = $wpdb->prepare( ‘query’ [, value_parameter, value_parameter … ] );

Щоб це було трохи більше легкотравно, давайте трохи перепишемо цей основний формат.

$sql = $wpdb->prepare( “INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value ) VALUES ( %d, %s, %d )”, 3342, ‘post_views’, 2290 )
$wpdb->query($sql);

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

Змінні класу та інші методи

Поряд з цими чудовими методами існує досить багато інших функцій для полегшення життя. Я покажу вам кілька звичайних, але, будь ласка, обов’язково подивіться повний список всього, що може запропонувати $wpdb, на сторінці Кодексу WordPress, посилання на який наведено вище.

insert_id()

Кожного разу при вставці чого-небудь в таблицю у вас там напевно з’явиться автоматично приріст ID. Щоб знайти значення самої останньої вставки, виконаної вашим скриптом, можна використовувати $wpdb->insert_id.

$sql = $wpdb->prepare( “INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value ) VALUES ( %d, %s, %d )”, 3342, ‘post_views’, 2290 )
$wpdb->query($sql);
$meta_id = $wpdb->insert_id;

num_rows()

Якщо ви в своєму скрипті виконали запит, то ця змінна поверне кількість результатів вашого останнього запиту. Це відмінно підходить для підрахунку постів, коментарів і так далі.

Назви таблиць

Всі базові назви таблиць зберігаються в змінних, назви яких в точності такі ж, як їх еквівалент основної таблиці. Назва таблиці постів (можливо, wp_posts) буде зберігатися у змінній $posts, так що ви могли б вивести її з допомогою $wpdb->posts.

Ми використовуємо її, тому що у нас є можливість вибирати префікс для своїх таблиць WordPress. У той час як більшість людей використовують префікс за замовчуванням wp, деякі користувачі хочуть або потребують користувальницькому префіксі. В ім’я гнучкості цей префікс жорстко не кодується, так що якщо ви пишете плагін та застосовуєте у запиті wp_postmeta замість $wpdb->postmeta, ваш код на деяких вебсайтах не стане працювати.

Якщо вам потрібно отримати дані з небазової таблиці WordPress, для цього немає жодної спеціальної змінної. У такому випадку ви можете просто написати назву таблиці, як зазвичай.

Керування повідомленнями про помилку

Викликаючи методи show_errors() або hide_errors(), можна включати або вимикати повідомлення про помилки (за замовчуванням вони виключені), щоб отримати більше інформації про те, що відбувається. У будь-якому випадку для роздруківки помилок останнього запиту ви також можете застосовувати метод print_error().

$wpdb->show_errors();
$wpdb->query(“DELETE FROM wp_posts WHERE post_id = 554 “);
// По причині того, що встановлений show_errors(), при запуску повідомлення про помилки скаже вам, що поле “post_id” невідомо
// поле цієї таблиці (так як правильне поле – це ID)

Побудова простого відстеження з застосуванням знання $wpdb

Якщо ви новачок, то, можливо, розумієте, про що я кажу, але, може бути, знаходите складним для реалізації. Отже, давайте візьмемо приклад простого плагіна відстеження WordPress, який я зробив для вебсайту.

Простоти заради я не стану описувати кожну деталь цього плагіна. Просто покажу структуру бази даних і кілька запитів.

Структура нашої таблиці

Щоб відстежити клацання і наведення миші на рекламних оголошеннях я створив таблицю; давайте назвемо її “tracking.” Ця таблиця записує дії користувачів у режимі реального часу. Кожне наведення і клацання записується в її власний ряд в такій структурі/порядку:

ID
Автоматично приращенное ID.

time
Дату та час здійснення дії.

deal_id
ID угоди, яке пов’язане з дією (тобто рекламний блок, на який клацали або дивилися).

action
Вид дії (тобто клацання або наведення).

action_url
Сторінка, на якій ініційовано дію.

user_id
ID користувача, якщо він залягання.

user_ip
IP користувача для усунення будь-яких злочинних намірів.

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

Вставка даних в таблиці

При клацанні користувача на рекламне оголошення він виявляється, а потрібна нам інформація надсилається в скрипт у формі масиві $_POST з наступними даними:

Array
(
[deal_id] => 643
[action] => click
[action_url] => http://thisiswhereitwasclicked.com/about/
[user_id] => 223
[user_ip] = 123.234.223.12
)

Потім ми можемо вставити ці дані в базу даних з допомогою нашого методу-помічника, як тут:

$wpdb->insert(‘tracking’, array(“deal_id” => 643, “action” => “click”, “action_url” => “http://thisiswhereitwasclicked.com/about/”,
“user_id” => 223, “user_ip” => “123.234.223.12”), array(“%d”, %s, %s, “%d”, “%s”));

З ризиком відходу в бік від справи я звернуся до деяких питань, які могли зацікавити вас в цьому окремо взятому прикладі. Ви могли подумати, а як же щодо валідації даних? Клацання міг вчинити від адміністратора вебсайту або користувач міг помилково клацнути двічі, чи могло статися безліч інших речей.

Ми вирішили, що, так як нам не потрібна статистика в реальному часі (достатньо щоденної статистики), немає сенсу перевіряти дані при кожному внесенні. Щодня в районі опівночі, під час низького рівня трафіку, дані збираються в нову таблицю. Перед групуванням даних ми забезпечуємо її очищення, видаляє дублікати і так далі. Дані, звичайно, екрануються перед вставкою в таблицю, тому що ми застосовуємо функцію-помічника; таким чином, тут ми себе убезпечили.

Просто видалити оптом все зроблене адміністраторами легше, ніж робити перевірку під час вставлення. Таким чином, з плечей сервера знімається тягар значної кількості обробки.

Видалення дій з IP, внесеного в «чорний список»

Якщо виявляється, що IP-адреса 168.211.23.43 дуже-дуже погано себе веде, ми можемо внести в «чорний список». У такому випадку при групуванні щоденних даних нам знадобиться видалити всі входи з цього IP.

$sql = $wpdb->prepare(“DELETE FROM tracking WHERE user_ip = %s “, ‘168.211.23.43’);
$wpdb->query($sql);

Ви, можливо, помітили, що я все ще экранирую дані, навіть якщо IP отриманий з безпечного джерела. Я запропонував би екранувати даних кров з носу. По-перше, справжні хакери гарні у своїй справі, тому що вони відмінні програмісти і можуть перехитрити вас такими способами, про яких ви і не подумали б. Крім цього, я особисто зробив більше на шкоду своїм вебсайтів, ніж хакери, так що я все це роблю і як засіб проти самого себе.

Оновлення підсумків

Ми зберігаємо свої рекламні оголошення користувальницькі типи постів; а для полегшення статистичної звітності зазвичай зберігаємо загальна кількість клацань, одержуваних оголошенням окремо. Можна було б просто скласти всі клацання з тим же успіхом у своїй базі даних tracking для даної угоди, так що давайте спочатку розглянемо це.

$total = $wpdb->get_var(“SELECT COUNT(ID) WHERE deal_id = 125 “);

Так як отримати окрему змінну легше, ніж постійно завантажувати себе більш складними запитами кожен раз при групуванні даних, можна було б зберігати поточну суму окремо. Наші рекламні оголошення зберігаються як пости з користувальницьким типом, так що логічно тримати цю суму в таблиці postmeta. Для зберігання цих даних давайте застосуємо мета-ключ total_clicks.

$wpdb->update( $wpdb->postmeta, array(“meta_value” => $total), array(“ID” => 125), array(“%d”), array(“%d”) );
// зверніть увагу, що це слід робити за допомогою update_post_meta(), я зробив це таким чином заради прикладу

Фінальні думки та підказки

Сподіваюся, тепер ви краще розумієте клас WordPress $wpdb і зможете застосовувати його для поліпшення своїх проектів. На закінчення ось вам декілька підказок і прийомів ефективного використання цього класу.

Я благаю вас бути обачними: разом з великими можливостями з’являється велика відповідальність. Забезпечте захист своїх даних і їх валідацію, тому що неправильне застосування цього класу – ймовірно основна причина зламаних веб-сайтів!

Запитуйте тільки ті дані, які вам потрібні. Якщо ви будете показувати назву статті, немає необхідності шукати всі дані з кожного рядка. В такому випадку просто запитуйте назва і ID: SELECT title, ID FROM wp_posts ORDER BY post_date DESC LIMIT 0,5.

У той час як можна застосовувати метод query()для будь-якого запиту, краще, де можливо, використовувати методи-асистенти (insert, update,get_row тощо). Вони більш модульні і безпечні, тому що автоматично екранують ваші дані.

Будьте обережні при видаленні записів з бази даних WordPress (або будь-який інший). Коли WordPress видаляє коментар, також відбувається безліч інших дій: потрібно зменшити на один підрахунок коментарів wp_poststable, всі дані з таблиці comment_meta також потребують видалення, і так далі. Переконайтеся, що ретельно прибираєте за собою, особливо при видаленні чого-небудь.

Почитайте в офіційній документації про всіх змінних класу та інші відомості. Це допоможе вам використовувати всі можливості класу. Я також рекомендую прочитати про загальну застосуванні класу ezSQL у ваших не-WordPress проектах; я застосовую його виключно майже скрізь.

На цьому урок з професійного взаємодії з базою даних в WordPress, закінчено.