Дорогие,
Я хочу удалить старое сообщение автоматически, без использования плагина, и выбором будут фрагменты. Я хочу удалить любое сообщение старше одного дня из специальной категории, используя этот фрагмент, но ничего не удалено:
// Automatically delete posts older than x days
function delete_old_posts($category_id = 62) {
$days = 1; // Change this value to the desired number of days
$args = array(
'post_type' => 'post',
'posts_per_page' => -1,
'date_query' => array(
array(
'before' => $days . ' days ago',
'inclusive' => true,
),
),
'tax_query' => array(
array(
'taxonomy' => 'slug', // Replace 'category' with your actual taxonomy slug if different
'field' => 'id',
'terms' => array($category_id), // Array of category IDs to target
),
),
);
$old_posts = new WP_Query($args);
if ($old_posts->have_posts()) :
while ($old_posts->have_posts()) : $old_posts->the_post();
wp_delete_post(get_the_ID(), true);
endwhile;
endif;
wp_reset_postdata();
}
add_action('wp', 'delete_old_posts');
В WP нет простого решения, вам придется использовать собственный SQL.
wp_terms
хранятся имена терминов с идентификатором, связанным с первичным ключом (PK).wp_term_relationships
— это таблица взаимосвязей между сообщениями и их таксономией/терминами.wp_term_taxonomy
представляет собой таблицу взаимосвязей между терминами и связанными с ними таксономиями.Внимание: всегда сначала проверяйте оператор SQL через SELECT
, прежде чем использовать неотменяемое действие, например удаление записей.
SELECT
*
FROM
wp_posts wp
WHERE
post_date <= DATE_SUB(NOW(), INTERVAL 6 HOUR)
AND
post_type = 'post'
AND
ID IN (
SELECT
wtr.object_id
FROM
wp_term_taxonomy wtt
JOIN wp_terms wt ON
wtt.term_id = wt.term_id
JOIN wp_term_relationships wtr ON
wt.term_id = wtr.term_taxonomy_id
WHERE
wtt.taxonomy = 'category'
AND wt.slug = 'temp');
WHERE
измените значение wt.slug
с temp
на желаемый ярлык категории.post_date <= DATE_SUB(NOW(), INTERVAL 6 HOUR)
измените интервал на желаемую единицу времени, например «Неделя», «День», «Час» и т. д. (Ссылка на единицу измерения: https://dev.mysql.com/doc/refman/8.0/en/expressions.html# временные интервалы)Если вас устраивает вывод оператора SELECT
, измените его на оператор DELETE
, как показано ниже.
DELETE
FROM
wp_posts wp
WHERE
post_date <= DATE_SUB(NOW(), INTERVAL 6 HOUR)
AND
post_type = 'post'
AND
ID IN (
SELECT
wtr.object_id
FROM
wp_term_taxonomy wtt
JOIN wp_terms wt ON
wtt.term_id = wt.term_id
JOIN wp_term_relationships wtr ON
wt.term_id = wtr.term_taxonomy_id
WHERE
wtt.taxonomy = 'category'
AND wt.slug = 'temp');
Вы можете использовать это:
<?php
function delete_posts_by_category_and_age_atakanau() {
// Set the category ID of the posts to be deleted
$category_id=11;
// Calculate the date 1 day ago
$one_day_ago = date('Y-m-d H:i:s', strtotime('-1 day'));
global $wpdb;
// Get posts ID older than 1 day with the given category ID
$query = $wpdb->prepare(
"SELECT posts.ID
FROM {$wpdb->posts} posts
INNER JOIN {$wpdb->term_relationships} term_relationships ON (posts.ID = term_relationships.object_id)
WHERE posts.post_type = 'post'
AND posts.post_status = 'publish'
AND term_relationships.term_taxonomy_id = %d
AND posts.post_date < %s",
$category_id,
$one_day_ago
);
$posts_to_delete = $wpdb->get_results($query);
// Loop through the posts to delete
foreach ($posts_to_delete as $post) {
// Use wp_delete_post to delete each post
wp_delete_post($post->ID, true); // Set second parameter to true to bypass the trash
}
}
add_action('plugins_loaded', 'delete_posts_by_category_and_age_atakanau');
Я рекомендую использовать его в дочерней теме вместо фрагмента. Крючок не может быть активирован с помощью фрагмента. Или вы можете вызвать функцию напрямую.
Возьмите функцию te_delete_old_posts(), если используете ее независимо, и нет необходимости в частях cron, если это не требуется.
// Function to set up a daily custom event.
function te_setup_daily_post_deletion_event() {
if (!wp_next_scheduled('te_daily_post_deletion_hook')) {
wp_schedule_event(time(), 'daily', 'te_daily_post_deletion_hook');
}
}
add_action('wp', 'te_setup_daily_post_deletion_event');
// Function to delete old posts.
function te_delete_old_posts() {
$category_id = 62; // Set your category ID.
$days = 1; // Posts older than this number of days will be deleted.
$query_date = date('Y-m-d', strtotime("-$days days"));
$args = array(
'post_type' => 'post',
'posts_per_page' => -1,
'fields' => 'ids', // Retrieve only the IDs for efficiency.
'date_query' => array(
array(
'before' => $query_date,
'inclusive' => false, // set to true if previous day is considered a day old
),
),
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => array($category_id),
),
),
);
$old_posts = get_posts($args); // Get a nice lean memory efficient list of post ID's
if (!empty($old_posts)) {
foreach ($old_posts as $post_id) {
wp_delete_post($post_id, true);
}
}
}
// Used for the cronjob method
add_action('te_daily_post_deletion_hook', 'te_delete_old_posts');
В приведенном ниже примере я извлек основной компонент запроса, чтобы вы могли добавить его в функцию и запустить ее.
Первоначально пройденная дата не соответствует ожиданиям. $query_date используется для получения правильной даты с помощью функций PHP date/strtotime без остатка времени.
Также я говорю запросу предоставлять только идентификаторы результатов, чтобы он был эффективнее, чем получение целых объектов сообщений.
Наконец, я использую get_posts(), чтобы мы могли получить чистый массив идентификаторов сообщений для циклического прохождения и не иметь дело с WP_Query().
$category_id = 62; // Set your category ID.
$days = 1; // Posts older than this number of days will be deleted.
$query_date = date('Y-m-d', strtotime("-$days days"));
$args = array(
'post_type' => 'post',
'posts_per_page' => -1,
'fields' => 'ids', // Retrieve only the IDs for efficiency.
'date_query' => array(
array(
'before' => $query_date,
'inclusive' => false, // set to true if previous day is considered a day old
),
),
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => array($category_id),
),
),
);
$old_posts = get_posts($args); // Get array of post ID's
if (!empty($old_posts)) {
foreach ($old_posts as $post_id) {
echo $post_id . " " get_the_title($post_id);
}
}
Запустив только этот код, вы можете убедиться, что получаете ожидаемые результаты, и, если нет, настроить запрос.
Если этот процесс является повторяющимся событием, как это видно из описания. Это должно быть выполнено в WP cronjob, чтобы процесс не продолжал работать каждый раз при загрузке страницы, как это было в перехватчике «wp». Я предполагаю, что это было для тестирования, или вы планировали сделать это вручную.
function te_setup_daily_post_deletion_event() {
if (!wp_next_scheduled('te_daily_post_deletion_hook')) {
wp_schedule_event(time(), 'daily', 'te_daily_post_deletion_hook');
}
}
add_action('wp', 'te_setup_daily_post_deletion_event');
Если вы не хотите использовать cronjob и хотите запустить его вручную, добавьте функцию te_delete_old_posts() в файл function.php вашей темы или в собственный плагин, и вы можете использовать один из двух методов, описанных ниже, для запуска этой функции.
wp eval "te_delete_old_posts();"
Нажмите Enter после ввода имени функции внутри оболочки.
wp shell
wp> te_delete_old_posts()
Ваш сценарий — довольно хорошее начало, и, похоже, вы на правильном пути. WordPress создает данные в нескольких таблицах, когда вы создаете сообщения, и важно, чтобы при удалении сообщения происходила правильная очистка. wp_delete_post() делает именно это.
И, как уже упоминалось, используйте код, который я предоставил для тестирования, и сначала убедитесь, что вы получаете результаты, если что-то не работает.
@TLDR спасибо за ваши добрые слова и вашу прекрасную поддержку..
'posts_per_page' => -1
может закрыть ваш сайт, если у вас больше сообщений, используйте лимит-1
осторожно, чтобы избежать отключения сайта и базы данных. Почемуwp_delete_post(get_the_ID(), true);
не является хорошим решением, так это то, что он удалит каждую запись по отдельности, поэтому вам придется выполнить n запросов для n количества сообщений, а не 1 запрос для n количества сообщений.