web-dev-qa-db-ja.com

有効期限が切れてから数日後に期限切れの投稿を削除する

ステータスが「期限切れ」のカスタム投稿を削除するには、次のコードを使用します( Jamie Keefer のおかげで)。投稿は、サードパーティのプラグインによって「期限切れ」として設定されています。ユーザーは自分の投稿(広告)へのフロントエンドアクセスのみを持ちます。

私の質問は次のとおりです。 投稿の投稿者が再公開しない場合は、有効期限が切れてから何日後に削除するか。 また、このコードを改善する方法についての提案をいただければ幸いです。

// 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

}
4
Iurie Malai

WP Cronの仕事は、イベントが発生したときに誰かがそのサイトにアクセスする必要があるため信頼できません。正確なタイミングが必要な場合は、サーバーのcronジョブを使用してください。

とにかく、あなたのコードと何が悪いのか見てみましょう、そして私たちはそれを修正することができます

  • wpはあなたの予定されたイベントをフックするのに使うより良いフックです、これは利用可能な最も早いpostdataです。 initは早期への道です。おそらく安全のためだと思います、template_redirectフックを試すこともできます。

  • あなたのコードは実行するのが非常に高価で、不必要にサーバーリソースを浪費します。以下を見てください。

    • 投稿ID以外の投稿データは必要ありません。他の投稿データは無駄になり、それを問い合わせることは多くのリソースを浪費します。大規模なサイトでは、これは実際にはタイムアウトによる致命的なエラーにつながる可能性があります。

    • 有効期限が切れ、有効期限が一定の期間に達した投稿のみを照会する必要があります。

すべてをコードに入れてみましょう。( 注: これはすべてテストされていません。また、コードの一部をコピーして貼り付けたので、 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' );
    }
}

これでうまくいくはずです。関数内で正しい時間枠を設定することを忘れないでください

5
Pieter Goosen

ネイティブのゴミ箱

あなた自身のWordPresstrashシステムのバージョンを実装しているようです。

ネイティブの方法で投稿をtrashした場合、投稿はtrash投稿ステータスになり、30日後に自動的に(完全に)削除されます。 wp-config.phpファイルでこれを変更することができます。

define( 'EMPTY_TRASH_DAYS', 10 );

例えば10日間。

独自のカスタムexpire投稿ステータスを作成する代わりに、 wp_trash_post( $post_id ) で投稿をゴミ箱に捨てることができます。

このようにしてあなたはシステムを あなたと働かせます ;-)

詳細については、Codexの trash status を確認してください。

3
birgire