場合によっては、WP_Query
オブジェクトに複数のpost&pageパラメータを使用すると便利な場合があります。私の場合は、親ページ自体も含めて、親ページの子を表示します。
私が達成したいことの可視化。次のページが次のように階層的にソートされているとします。
太字のリスト項目は検索したい投稿/ページです。
私の最初の考えは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
の ドキュメント を見てください。
生成された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
に渡された親を返します、そしてそれは子供です
あなたが望むのが "page" post_typeからの結果だけであれば、@ birgireが提案したようにしてください。
あるいは、page
post_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句を解析するのと同じことですが、これはまったく同じことを達成します。
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>
私があなたを正しく理解しているならば、あなたは親とそれ以降のすべての子ページの両方のIDを取得したいです。 Wordpressには、次のようにページの子を取得する関数があります。
https://codex.wordpress.org/Function_Reference/get_page_children
私は、WP_Queryを実行しているので、すでに親ページのIDを取得していることを理解しています。したがって、必要なことは、必要なものを取得するために関連IDを上記関数に渡すことだけです。
注:この関数はDBクエリを実行しないので、DBへのクエリのみを実行しているため、パフォーマンスは向上します。
$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());
これはうまくいくようです。コメント?