web-dev-qa-db-ja.com

最新のX投稿を除くWordPressからすべての投稿を削除する

プロジェクトでは、私はウェブサイトに最新の投稿を10件だけ残して、他のすべての投稿を自動削除する必要があります。それで私はポストパブリッシュ/アップデートでトリガーするこの関数を思いつきました、そして私は最新の10アイテムを除外するためにoffsetパラメータを使いました。

function wpse_auto_delete_posts( $post_ID ) {
  global $post;

  $delete_posts = get_posts( array( 'post_type' => 'post', 'offset' => 10, 'posts_per_page' => -1 ) );
  foreach ( $delete_posts as $delete_post ) : setup_postdata( $delete_post );
    wp_delete_post( $delete_post->ID, true );
  endforeach;
  wp_reset_postdata();

}
add_action( 'publish_post', 'wpse_auto_delete_posts' );

しかし、offset'posts_per_page' => -1ではここでは機能せず、すべての投稿を削除し続けます。日付クエリを使用することを考えましたが、新しい投稿が頻繁に作成されるため、それも機能しません。

最新の10または5以外のすべての投稿を選択する方法はありますか。したがって、WordPressはそれらを処理して最新のX投稿を保持できます。

6
Robert hue

offsetパラメーターは、posts_per_page-1WP_Queryに設定されていると無視されます。 WP_Queryクラスのソースコードを見ると、posts_per_page=-1nopagingをtrueに設定します。

if ( !isset($q['nopaging']) ) {
    if ( $q['posts_per_page'] == -1 ) {
        $q['nopaging'] = true;
    } else {
        $q['nopaging'] = false;
    }
}

これはSQLクエリにLIMITを追加しません(empty($q['nopaging'] === falseこれは条件文に失敗します)。つまり、ページ区切り/オフセット全体は無視され、すべての投稿が返されます。

if ( empty($q['nopaging']) && !$this->is_singular ) {
    $page = absint($q['paged']);
    if ( !$page )
        $page = 1;

    if ( empty($q['offset']) ) {
        $pgstrt = absint( ( $page - 1 ) * $q['posts_per_page'] ) . ', ';
    } else { // we're ignoring $page and using 'offset'
        $q['offset'] = absint($q['offset']);
        $pgstrt = $q['offset'] . ', ';
    }
    $limits = 'LIMIT ' . $pgstrt . $q['posts_per_page'];
}

私はここで最もよい回避策はすべての投稿を得た後に通常のPHP(array_slice())を利用することであると思います。 wp_delete_postは実行するのが非常に高価で実際には投稿IDのみが必要なので、ここでは投稿IDのみを取得したいので、他の投稿情報は必要ありません。

つまり、クエリは次のようになります。(NOTE:これはすべてテストされておらず、PHP 5.4+

add_action( 'publish_post', function ( $post_ID ) 
{
    $args = [
        'nopaging' => true,
        'fields'   => 'ids'
    ];
    $posts_array = get_posts( $args );
    // Make sure that we have post ID's returned
    if ( $posts_array ) {
        // Get all post ids after the 10th post using array_slice
        $delete_posts = array_slice( $posts_array, 10 );
        // Make sure that we actually have post ID's in the $delete_posts array
        if ( $delete_posts ) {
            foreach ( $delete_posts as $delete_post )
                wp_delete_post( $delete_post, true );
        }
    }
});

_編集_

忘れる直前に、posts_per_pageの代わりに-1をあり得ない整数値として定義することもできます。これはoffsetパラメータを設定したコードでも動作します。

6
Pieter Goosen

'nopaging' => true'posts_per_page' => -1が同じ動作をするという事実。このパラメータはあなたのWPによってなされたMySQLリクエストのLIMIT節をキャンセルしています。

offset(int) - 移動または通過するポストの数警告:offsetパラメータを設定すると、ページングされたパラメータが上書きされて無視され、ページ付けが中断されます(回避策についてはここをクリックしてください)。 'posts_per_page' => - 1(すべての投稿を表示)が使用されている場合、 'offset'パラメータは無視されます。

MySQLのドキュメント およびそれらの推奨事項を考慮すると、offsetをそのままにして、posts_per_pageパラメータに多数の値を使用できます。

特定のオフセットから結果セットの最後までのすべての行を取得するには、2番目のパラメータに大きな数を使用できます。このステートメントは、96行目から最後までのすべての行を取得します。

SELECT * FROM tbl LIMIT 95,18446744073709551615;

0
Ignat B.