web-dev-qa-db-ja.com

WP_Queryを使用して親の投稿をその子と一緒に返しますか?

場合によっては、WP_Queryオブジェクトに複数のpost&pageパラメータを使用すると便利な場合があります。私の場合は、親ページ自体も含めて、親ページの子を表示します。

私が達成したいことの可視化。次のページが次のように階層的にソートされているとします。

  • ページA
  • Bページ
    • 子ページA
    • 子ページB
    • 子ページC
  • ページC

太字のリスト項目は検索したい投稿/ページです。

私の最初の考えはWP_Queryのためにこれら二つのパラメータを使って出かけます:

$args = array(
   'post_id' => $parent->ID,
   'post_parent' => $parent->ID,
);

残念ながら、ここでは1つのパラメータしか使用しません。上記の$args(間違っている場合は訂正してください)を使うと、親の投稿のすべての子の投稿と、親の投稿自体のnotも出力されます。

この問題は、必要な投稿をすべて集め、それらを次のようにパラメータpost__inに入れることで解決されるかもしれません。

$args = array(
   'post__in' => $children_and_parent_ids,
);

ただし、 wp_list_pages() を使用すると、投稿をincludeにして、(child_of)の子を含める場所を指定できます。 WP_Queryではこれが不可能なのはなぜですか?

私がwp_list_pages()を使って達成しようとしていることの例:

wp_list_pages(array(
    'include' => $parent->ID,
    'child_of' => $parent->ID,
));

WP_Queryドキュメント を見てください。

5
Fleuv

生成されたSQLのposts_where句をフィルタ処理して、親の子だけでなく親の投稿/ページも返すことができます。ここではwpse_include_parentと呼ばれる独自のカスタム引数を設定します。これはtrueに設定されるとそれに応じて生成されたSQLを変更します。

posts_whereフィルタの中でやらなければならないことは、カスタム引数が設定されているかどうか、およびpost_parent引数が設定されているかどうかを確認することだけです。それからその値を取得し、それをフィルタに渡してSQLクエリを拡張します。ここでいいのは、post_parentは単一の整数値を除いて、その値を整数として検証するだけでよいということです。

質問

$args = [
    'wpse_include_parent' => true,
    'post_parent'         => 256,
    'post_type'           => 'page'
    // Add additional arguments
];
$q = new WP_Query( $args );

ご覧のとおり、'wpse_include_parent' => trueをフィルタを「有効にする」ように設定しました。

フィルター

add_filter( 'posts_where', function ( $where, \WP_Query $q ) use ( &$wpdb )
{
    if ( true !== $q->get( 'wpse_include_parent' ) )
        return $where;

    /**
     * Get the value passed to from the post parent and validate it
     * post_parent only accepts an integer value, so we only need to validate
     * the value as an integer
     */
    $post_parent = filter_var( $q->get( 'post_parent' ), FILTER_VALIDATE_INT );
    if ( !$post_parent )
        return $where;

    /** 
     * Lets also include the parent in our query
     *
     * Because we have already validated the $post_parent value, we 
     * do not need to use the prepare() method here
     */
    $where .= " OR $wpdb->posts.ID = $post_parent";

    return $where;
}, 10, 2 );

あなたは必要に応じてこれを拡張することができ、見やすいですが、これが基本的な考え方です。これはpost_parentに渡された親を返します、そしてそれは子供です

5
Pieter Goosen

あなたが望むのが "page" post_typeからの結果だけであれば、@ birgireが提案したようにしてください。

あるいは、pagepost_typeだけでなく、任意のカスタム投稿タイプについても同様の結果が得られるように、以下を変更することができます。

$parent = 2;      //change as desired
$type   = 'page'; //change as desired

$child_args = array( 
    'post_type'   => $type, 
    'post_parent' => $parent 
);

$ids = array($parent);
$ids = array_merge($keys, array_keys( get_children( $child_args ) ));

$query = new WP_Query( 
    array( 
        'post_type'      => 'page', 
        'post_status'    => 'publish', 
        'post__in'       => $ids, 
        'posts_per_page' => -1 
    ) 
);

上記は基本的にposts_whereフィルタにフックしてSQL句を解析するのと同じことですが、これはまったく同じことを達成します。

5
userabuser

global $wpdb[get_results()][1]と組み合わせて使用​​することもオプションです。パフォーマンス面で私はこれが1つのクエリだけを実行するのでこれが最善の解決策だと思います。

これが私の最後のコードです。

<ul class="tabs"><?php

    global $wpdb, $post;

    $parent = count(get_post_ancestors($post->ID))-1 > 0 ? $post->post_parent : $post->ID;

    $sql = "SELECT ID FROM `{$wpdb->prefix}posts`";
    $sql.= " WHERE ID='{$parent}' OR post_parent='{$parent}' AND post_type='page'";
    $sql.= " ORDER BY `menu_order` ASC";

    $tabs = $wpdb->get_results($sql);

    $output = '';
    foreach ($tabs as $tab) {
        $current = $post->ID == $tab->ID ? ' class="active"' : '';

        $output .= '<li'.$current.'>';
        $output .= empty($current) ? '<a href="'.get_permalink($tab->ID).'">' : '';
        $output .=   get_the_post_thumbnail($tab->ID, 'menu-24x24');
        $output .=   '<span>'.get_the_title($tab->ID).'</span>';
        $output .= empty($current) ? '</a>' : '';
        $output .= '</li>';
    }
    print $output;

?></ul>
0
Fleuv

私があなたを正しく理解しているならば、あなたは親とそれ以降のすべての子ページの両方のIDを取得したいです。 Wordpressには、次のようにページの子を取得する関数があります。

https://codex.wordpress.org/Function_Reference/get_page_children

私は、WP_Queryを実行しているので、すでに親ページのIDを取得していることを理解しています。したがって、必要なことは、必要なものを取得するために関連IDを上記関数に渡すことだけです。

注:この関数はDBクエリを実行しないので、DBへのクエリのみを実行しているため、パフォーマンスは向上します。

0
EBennett
    $args = array(
        'post_type' => 'tribe_events',
        'posts_per_page' => '-1',
        'orderby' => 'ID',
        'order' => 'ASC',
        'post_parent' => $postID,
    );

    $children = new WP_Query($args);
    $parent[] = get_post($postID);
    $family = array_merge($parent, $children->get_posts());

これはうまくいくようです。コメント?

0
egauvin