
🔒 4 Способи програмно зняти пост з публікації в wordpress
Сайт упав після оновлення плагіна, потрібно терміново приховати проблемний пост, поки не пізно. А через тиждень повернути назад, коли баг полагодять. Або клієнт просить прибрати застарілу статтю з видачі, але не видаляти назавжди.
Ручне перемикання статусу через адмінку працює для одного-двох постів. Але коли таких десятки або логіка має спрацьовувати автоматично, потрібен програмний підхід. WordPress дає чотири способи зняти пост із публікації через PHP: від безпечної чернетки до повного видалення.
Нижче, кожен метод із готовим кодом, поясненням і підказкою, коли який застосовувати.
💡 Швидкий огляд:
- Перевели пост у чернетку через
wp_update_postзі статусомdraft, найбезпечніший і оборотний спосіб - Зробили пост приватним (
private), видно лише адміністраторам і редакторам - Відправили пост у майбутнє через
post_date, пост зникає з видачі до настання заданої дати - Видалили пост назавжди через
wp_delete_post, крайній захід із попередженнями та бекапом
Крок 1. Чернетка: знімаємо пост із публікації без втрати даних
Найчастіший сценарій: потрібно тимчасово приховати пост, але зберегти весь контент, URL і можливість повернути назад одним кліком. Переведення в чернетку, ідеальний варіант.
Змінюється лише поле post_status у таблиці wp_posts. Сам пост, його мета-поля, вкладення та URL залишаються недоторканими. Коли вирішите повернути, змінюєте статус назад на publish.
Код для зміни статусу на draft. Додайте в functions.php дочірньої теми або через плагін Code Snippets:
1 /** 2 * Переводить пост у чернетку за ID. 3 * 4 * @param int $post_id ID поста, який потрібно зняти з публікації. 5 */ 6 function sd_unpublish_to_draft( $post_id ) { 7 wp_update_post( array( 8 'ID' => $post_id, 9 'post_status' => 'draft', 10 ) ); 11 } 12 13 // Приклад виклику: знімаємо пост з ID = 42 14 sd_unpublish_to_draft( 42 );
wp_update_post() оновлює запис у БД. Ми передаємо лише ID і нове значення post_status, усе інше WordPress підхоплює сам. Жодні інші поля не змінюються.
Коли застосовувати: тимчасове приховування поста на доопрацювання, автоматична деактивація постів із простроченим терміном актуальності (наприклад, акції), програмна модерація користувацького контенту.
Крок 2. Приватний пост: приховуємо від відвідувачів, залишаємо редакторам
Приватний статус — це середина між публічним і прихованим. Пост не видно звичайним відвідувачам, але доступний адміністраторам і редакторам в адмінці. Зручно для внутрішніх матеріалів: інструкцій для команди, чернеток клієнтського контенту, закритих сторінок.
Відмінність від чернетки: приватний пост технічно «опублікований» і може мати свій URL, але WordPress перевіряє права користувача перед показом. Відвідувач без ролі read_private_posts побачить 404.
Код аналогічний попередньому, змінюється лише статус:
1 /** 2 * Робить пост приватним — видимим лише адмінам і редакторам. 3 * 4 * @param int $post_id ID поста. 5 */ 6 function sd_unpublish_to_private( $post_id ) { 7 wp_update_post( array( 8 'ID' => $post_id, 9 'post_status' => 'private', 10 ) ); 11 } 12 13 // Приклад виклику 14 sd_unpublish_to_private( 42 );
Зверніть увагу: якщо на сайті є користувацькі ролі з кастомними правами, перевірте capabilities перед масовим використанням. За замовчуванням приватні пости бачать ролі editor і administrator.
Коли застосовувати: преміум-контент за підпискою (у зв'язці з membership-плагінами), внутрішня документація команди, приховування постів для переузгодження з клієнтом перед повторною публікацією.
Крок 3. Майбутня дата: відкладене зняття з публікації
Цікавий прийом: замість зміни статусу можна «відправити пост у майбутнє», задати дату публікації на 2050 рік. Пост миттєво зникає з видачі, тому що WordPress показує лише пости з датою ≤ поточному моменту.
Цей метод не змінює post_status: пост залишається publish. Він просто «ще не настав» із погляду WordPress. Плюс, за потреби можна повернути реальну дату, і пост знову з'явиться.
Код використовує поля post_date і post_date_gmt:
1 /** 2 * Приховує пост, встановлюючи дату публікації у далеке майбутнє. 3 * 4 * @param int $post_id ID поста. 5 */ 6 function sd_unpublish_to_future( $post_id ) { 7 $future_date = '2050-12-31 23:59:59'; 8 9 wp_update_post( array( 10 'ID' => $post_id, 11 'post_date' => $future_date, 12 'post_date_gmt' => get_gmt_from_date( $future_date ), 13 ) ); 14 } 15 16 // Приклад виклику 17 sd_unpublish_to_future( 42 );
get_gmt_from_date() конвертує локальний час у GMT, WordPress зберігає обидві версії дати. Не нехтуйте GMT-полем: без нього поведінка при зміні часового поясу сайту стане непередбачуваною.
Коли застосовувати: «відкладена» публікація контенту за розкладом, тимчасове приховування новин без зміни статусу, сценарії, де post_status має залишитися publish для зворотної сумісності з іншими плагінами.
Крок 4. Видалення: коли пост не потрібен зовсім
wp_delete_post(), необоротна операція. Пост видаляється з бази, а разом із ним, усі мета-поля, зв'язки з таксономіями та (опціонально) вкладення.
Це не «зняття з публікації» в строгому сенсі. Але в контексті програмного управління контентом видалення, четвертий, найжорсткіший інструмент. І він вимагає запобіжників.
Перед запуском зробіть повний бекап бази даних. Скрипт нижче спочатку виводить список того, що буде видалено, і лише потім, бойовий варіант.
1 /** 2 * Видаляє пост. Спочатку — dry-run з виводом інформації, потім — бойове видалення. 3 * 4 * УВАГА: необоротна операція. Зробіть бекап перед запуском. 5 * 6 * @param int $post_id ID поста. 7 * @param bool $force_delete true — видалити назавжди (минаючи корзину), false — у корзину. 8 */ 9 function sd_delete_post_safe( $post_id, $force_delete = false ) { 10 $post = get_post( $post_id ); 11 12 if ( ! $post ) { 13 error_log( "Post with ID {$post_id} not found." ); 14 return; 15 } 16 17 // Dry-run: виводимо інформацію без видалення 18 error_log( sprintf( 19 'READY TO DELETE: ID=%d, title="%s", status=%s, attachments=%d', 20 $post->ID, 21 $post->post_title, 22 $post->post_status, 23 count( get_attached_media( '', $post_id ) ) 24 ) ); 25 26 // Розкоментуйте наступний рядок для реального видалення: 27 // wp_delete_post( $post_id, $force_delete ); 28 } 29 30 // Dry-run: тільки виводить інформацію 31 sd_delete_post_safe( 12341, false );
Прапорець $force_delete:
false, пост потрапляє в кошик (Trash), його можна відновити протягом 30 днів.true, видалення назавжди, відновити не можна навіть через базу (без бекапу).
Функція логує через error_log(), повідомлення з'являться у wp-content/debug.log при ввімкненому WP_DEBUG. У продакшені замініть на свій механізм сповіщень.
Коли застосовувати: автоматичне очищення спам-постів, видалення простроченого контенту (вакансії, заходи), програмна ротація контенту з повним видаленням старих записів.
Порівняння чотирьох методів
Метод | Статус поста | Оборотність | Видимість для читачів | Видимість в адмінці | Коли застосовувати |
|---|---|---|---|---|---|
Чернетка |
| Повна | Приховано | Усім ролям із доступом до постів | Тимчасове приховування, доопрацювання |
Приватний |
| Повна | Приховано | Адмінам і редакторам | Внутрішній контент, преміум |
Майбутня дата |
| Повна | Приховано до дати | Усім | Відкладена публікація, розклад |
Видалення | - | Тільки з кошика (30 днів) | - | Тільки адмінам | Повне видалення, очищення |
⁉️🤔 Часті запитання
Чим відрізняється зняття з публікації від видалення?
Зняття з публікації (draft/private/future) зберігає пост у базі: контент, URL, вкладення та SEO-історія залишаються. Видалення (
wp_delete_post) стирає запис повністю. Для тимчасового приховування завжди використовуйте чернетку — це безпечно й оборотно за секунду.
Який метод не вимагає зміни post_status?
Відправка в майбутнє через
post_date. Пост залишаєтьсяpublish, але WordPress вважає його «ще не насталим» і не показує відвідувачам. Це може бути важливо, якщо інші плагіни або сніпети зав'язані на статусpublish.
Чи можна зняти з публікації одразу кілька постів?
Так, обгорніть виклик функції в цикл по масиву ID. Додайте
wp_die()або обмеження на кількість постів за раз, щоб не покласти сайт при масовій операції:array_slice($post_ids, 0, 50)для батча по 50.
Чи потрібно очищати кеш після програмної зміни статусу?
Обов'язково. WordPress скидає внутрішній кеш поста при виклику
wp_update_post(), але зовнішній кеш (плагіни на кшталт WP Rocket, серверний кеш, CDN) потрібно скидати окремо. Додайте викликwp_cache_flush()або хукclean_post_cacheпісля зміни статусу.
Чи безпечно запускати wp_delete_post у продакшені?
Тільки із запобіжниками. Перед викликом: (1) перевірте
current_user_can('delete_posts'), (2) запитайте підтвердження через окремий nonce-токен, (3) логуйте ID і заголовок поста, що видаляється. І головне, бекап. Навіть у кошику пост живе 30 днів, після чого WordPress видаляє його автоматично.
Що використовувати у вашому випадку: підсумковий розклад
Чотири методи закривають майже будь-який сценарій програмного управління публікаціями. Вибір зводиться до одного запитання: чи потрібно зберегти пост?
- Якщо пост тимчасово приховати на доопрацювання, беріть чернетку (
draft). Пара рядків, нуль ризику. - Якщо контент для обмеженого кола осіб, приватний статус (
private). Редактори бачать, відвідувачі, ні. - Якщо потрібно приховати пост без зміни статусу, майбутня дата (
post_dateу 2050 рік). Хитрий, але робочий прийом. - Якщо пост точно не знадобиться, видалення (
wp_delete_post). Але спочатку dry-run і повний бекап.
Почніть з обгортки в functions.php для одного методу, наприклад, чернетки. Коли зрозумієте логіку wp_update_post(), решта трьох способів зберуться за п'ять хвилин.
А яким методом ви користуєтеся для програмного управління постами? Напишіть у коментарях, цікаво порівняти підходи.



