Автоматическое удаление старых сообщений с помощью фрагментов для специальной категории

Дорогие,

Я хочу удалить старое сообщение автоматически, без использования плагина, и выбором будут фрагменты. Я хочу удалить любое сообщение старше одного дня из специальной категории, используя этот фрагмент, но ничего не удалено:

// 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');
'posts_per_page' => -1 может закрыть ваш сайт, если у вас больше сообщений, используйте лимит -1 осторожно, чтобы избежать отключения сайта и базы данных. Почему wp_delete_post(get_the_ID(), true); не является хорошим решением, так это то, что он удалит каждую запись по отдельности, поэтому вам придется выполнить n запросов для n количества сообщений, а не 1 запрос для n количества сообщений.
gvgvgvijayan 28.03.2024 14:20
Как убрать количество товаров в категории WooCommerce
Как убрать количество товаров в категории WooCommerce
По умолчанию WooCommerce показывает количество товаров рядом с категорией, как показано ниже.
2
1
120
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Нет простого решения:

В WP нет простого решения, вам придется использовать собственный SQL.

Базовое понимание таблицы должностей и терминов и их взаимосвязи:

  • В таблице wp_terms хранятся имена терминов с идентификатором, связанным с первичным ключом (PK).
  • Таблица wp_term_relationships — это таблица взаимосвязей между сообщениями и их таксономией/терминами.
  • Таблица wp_term_taxonomy представляет собой таблицу взаимосвязей между терминами и связанными с ними таксономиями.

SQL:

Внимание: всегда сначала проверяйте оператор 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');

Я рекомендую использовать его в дочерней теме вместо фрагмента. Крючок не может быть активирован с помощью фрагмента. Или вы можете вызвать функцию напрямую.

Ответ принят как подходящий

TLDR;

Возьмите функцию 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');

Запуск с WP-CLI

Если вы не хотите использовать cronjob и хотите запустить его вручную, добавьте функцию te_delete_old_posts() в файл function.php вашей темы или в собственный плагин, и вы можете использовать один из двух методов, описанных ниже, для запуска этой функции.

wp eval "te_delete_old_posts();"

Нажмите Enter после ввода имени функции внутри оболочки.

wp shell
wp> te_delete_old_posts()

Всегда используйте wp_delete_post() для удаления сообщений:

Ваш сценарий — довольно хорошее начало, и, похоже, вы на правильном пути. WordPress создает данные в нескольких таблицах, когда вы создаете сообщения, и важно, чтобы при удалении сообщения происходила правильная очистка. wp_delete_post() делает именно это.

И, как уже упоминалось, используйте код, который я предоставил для тестирования, и сначала убедитесь, что вы получаете результаты, если что-то не работает.

@TLDR спасибо за ваши добрые слова и вашу прекрасную поддержку..

Ahmed Alnaqa 31.03.2024 23:19

Другие вопросы по теме