过期的帖子在过期几天后删除

时间:2015-11-18 作者:Iurie

我使用以下代码删除状态为“过期”的自定义帖子(感谢Jamie Keefer). 第三方插件将帖子设置为“过期”。用户只能通过前端访问其帖子(广告)。

我的问题是:how to delete them after a number of days after they expired if post authors don\'t republish them? 此外,如果您能就如何改进此代码提出建议,我将不胜感激。

// expired_post_delete hook fires when the Cron is executed
add_action( \'expired_post_delete\', \'delete_expired_posts\' );

// This function will run once the \'expired_post_delete\' is called
function delete_expired_posts() {

    $todays_date = current_time(\'mysql\');

    $args = array(
        \'post_type\' => \'advert\',
        \'post_status\' => \'expired\',
        \'posts_per_page\' => -1
    );

    $posts = new WP_Query( $args );

    // The Loop
    if ( $posts->have_posts() ) {

        while ( $posts->have_posts() ) {
            $posts->the_post();
            wp_delete_post(get_the_ID());
        }

    } else {
            // no posts found
    }

    /* Restore original Post Data */
    wp_reset_postdata();
}

// Add function to register event to WordPress init
add_action( \'init\', \'register_daily_post_delete_event\');

// Function which will register the event
function register_daily_post_delete_event() {
    // Make sure this event hasn\'t been scheduled
    if( !wp_next_scheduled( \'expired_post_delete\' ) ) {
        // Schedule the event
        wp_schedule_event( time(), \'daily\', \'expired_post_delete\' );
    }
}

UPDATE

以下是如何将帖子设置为“过期”:

add_action( \'adverts_event_expire_ads\', \'adverts_event_expire_ads\' );

/**
 * Expires ads
 * 
 * Function finds Adverts that already expired (value in _expiration_date
 * meta field is lower then current timestamp) and changes their status to \'expired\'.
 * 
 * @since 0.1
 * @return void
 */
function adverts_event_expire_ads() {

    // find adverts with status \'publish\' which exceeded expiration date
    // (_expiration_date is a timestamp)
    $posts = new WP_Query( array( 
        "post_type" => "advert",
        "post_status" => "publish",
        "meta_query" => array(
            array(
                "key" => "_expiration_date",
                "value" => current_time( \'timestamp\' ),
                "compare" => "<="
            )
        )
    ) );


    if( $posts->post_count ) {
        foreach($posts->posts as $post) {
            // change post status to expired.
            $update = wp_update_post( array( 
                "ID" => $post->ID,
                "post_status" => "expired"
            ) );
        } // endforeach
    } // endif

}

2 个回复
最合适的回答,由SO网友:Pieter Goosen 整理而成

WP Cron作业不可靠,因为它需要有人在事件发生时访问站点。如果需要精确计时,应该使用服务器cron作业。

不管怎样,让我们看看你的代码和哪里出了问题,我们可以修复它

  • wp 是一个更好的钩子,用于钩住计划的事件,这是postdata可用的最早的钩子。init 是早来的方式。我想为了安全起见,你也可以试试template_redirect

    运行您的代码非常昂贵,不必要地浪费了服务器资源。我们需要了解以下内容:

    除了post ID之外,我们不需要任何postdata。任何其他postdata都是无用的,查询它会浪费大量资源。在大型站点上,由于超时,这实际上可能导致致命错误

    我们只需要查询已经过期并且过期日期已经达到一定时间范围的帖子。

    让我们把一切都写进代码中:(NOTE: 这都是未经测试的,我还复制并粘贴了您的一些代码,因此我可能遗漏了一些内容,而且代码需要PHP 5.4+)

    function get_exired_posts_to_delete()
    {
        /**
         * If you need posts that expired more than a week ago, we would need to
         * get the unix time stamp of the day a week ago. You can adjust the relative 
         * date and time formats as needed. 
         * @see http://php.net/manual/en/function.strtotime.php
         * @see http://php.net/manual/en/datetime.formats.php
         */
        // As example, we need to get posts that has expired more than 7days ago
        $past = strtotime( "- 1 week" );
    
        // Set our query arguments
        $args = [
            \'fields\'         => \'ids\', // Only get post ID\'s to improve performance
            \'post_type\'      => \'advert\',
            \'post_status\'    => \'expired\',
            \'posts_per_page\' => -1,
            \'meta_query\'     => [
                [
                    \'key\'     => \'_expiration_date\',
                    \'value\'   => $past,
                    \'compare\' => \'<=\'
                ]
            ]
        ];
        $q = get_posts( $args );
    
        // Check if we have posts to delete, if not, return false
        if ( !$q )
            return false;
    
        // OK, we have posts to delete, lets delete them
        foreach ( $q as $id )
            wp_delete_post( $id );
    }
    
    现在我们可以创建自定义挂钩来挂钩函数

    // expired_post_delete hook fires when the Cron is executed
    add_action( \'expired_post_delete\', \'get_exired_posts_to_delete\' );
    
    最后,安排我们的活动

    // Add function to register event to wp
    add_action( \'wp\', \'register_daily_post_delete_event\');
    function register_daily_post_delete_event() {
        // Make sure this event hasn\'t been scheduled
        if( !wp_next_scheduled( \'expired_post_delete\' ) ) {
            // Schedule the event
            wp_schedule_event( time(), \'daily\', \'expired_post_delete\' );
        }
    }
    
    这应该可以做到,只需记住在函数中设置正确的时间范围

SO网友:birgire

本机垃圾桶

听起来你在实现自己版本的WordPresstrash 系统

如果你以本机方式丢弃帖子,它将获得trash 发布状态,并将在30天后自动(永久)删除。你可以在你的wp-config.php 使用文件:

define( \'EMPTY_TRASH_DAYS\', 10 );
例如10天。

然后你可以用wp_trash_post( $post_id ) 而不是创建自己的自定义expire post状态。

这样系统就可以正常工作with you ;-)

有关更多信息,请查看trash status 在法典中。