web-dev-qa-db-ja.com

親のカスタム投稿タイプの投稿のみを除外

これが何らかのハードコーディングなしで可能かどうかはわからないが、私は 'city'というカスタム投稿タイプを持っている。 'city'ポストタイプの中で、私はいくつかの親のポスト(例えばイギリス、アメリカ、中国)といくつかの子供のポスト(ロンドン、ワシントンDC、北京)を持っています。

「city」の下にすべての投稿を表示するクエリがあります。しかし、この特定のクエリでは、親の投稿(イギリス、アメリカ、中国)は無視し、子の投稿(ロンドン、ワシントン、北京)のみを表示します。

これが私のクエリをコーディングしている方法です:

<?php $city = new WP_Query(array('post_type' => 'city', 'orderby' => 'name', 'order' => 'ASC', 'posts_per_page' => -1 )); ?>
                            <?php while ($city->have_posts() ) : $city->the_post(); ?>
                                <?php the_title(); ?>
                            <?php endwhile; ?>

それでこれは可能ですか?私は反対のことをすることはより一般的な質問(親のみを表示し、子供を除く)であると考えていたでしょうが、私は私の問題が可能であることを願っています!

ありがとう

2
remi90

WP_Queryのコーデックス によると、解決策はトップレベルの投稿のIDとしてpost_parentを使用することです。しかし、あなたのケースにはロッタのトップレベルのcptが全部あるので、私はこの解決法があなたを助けるべきだと思います: WP_Queryを介してトップレベルの投稿だけをループで表示する方法?

更新:

<?php
    $all = get_posts(array('post_type'=> 'city', 'posts_per_page' => -1));
    $parents = array();
    foreach ($all as $single)
    {
        $kids = get_children($single->ID);  
        if(isset($kids) && !empty($kids) && count($kids) >= 1)
        {
            $parents[] = $single->ID;
        }
    }

    $args = array('post_type' => 'city', 'orderby' => 'name', 'order' => 'ASC', 'posts_per_page' => -1, 'post__not_in' => $parents );

    $city = new WP_Query($args);
    while ($city->have_posts() ) : $city->the_post();
            echo get_the_title()."<br />";
    endwhile;
    wp_reset_postdata();
?>

これは長い道のりですが、うまくいきます。クエリに含める前に、$ parent配列が空でないことを確認してください。

1

欲しいのは、posts_whereフィルタです。これにより、get_postsが生成するSQLクエリにWHERE句を追加できます。これにより、親の投稿のみを取得するためにデータベースにアクセスする手間が省けます。

フックされた関数は二つの引数を受け取ります:WHERE節自身とクエリオブジェクトです。クエリがcity投稿タイプに対するものであるかどうかを確認し、そこからwhere句を変更します。

<?php
add_filter( 'posts_where', 'wpse29897_no_parents', 10, 2 );
function wpse29897_no_parents( $where, $query )
{
    if( isset( $query->query_vars['post_type'] ) && 'city' == $query->query_vars['post_type'] )
    {
        if( '' != $where )
        {
            $where .= ' AND post_parent !=  0';
        }
        else
        {
            $where .= ' post_parent != 0';
        }
    }
    return $where;
}

ただし、cityという投稿タイプを含むすべてのクエリでこれが発生しないようにする必要があります。そのため、新しいWP_Queryオブジェクトを作成する場所のすぐ上にadd_filter呼び出しを固定することをお勧めします。それからwpse29897_no_parentsファイルまたはプラグインにfunctions.php関数を貼り付けます。

<?php 
add_filter( 'posts_where', 'wpse29897_no_parents', 10, 2 );
$city = new WP_Query(array('post_type' => 'city', 'orderby' => 'name', 'order' => 'ASC', 'posts_per_page' => -1 ));
while ($city->have_posts() ) : $city->the_post(); 
?>
    <?php the_title(); ?>
<?php endwhile; ?>

念のため、ループの後にフィルタを削除することもできます。

<?php remove_filter( 'posts_where', 'wpse29897_no_parents', 10, 2 ); ?>
1
chrisguitarguy