web-dev-qa-db-ja.com

WPはWPクエリを使用して、親のすべてのサブページを取得

これが私のコードです

$my_wp_query = new WP_Query();
$all_wp_pages = $my_wp_query->query(array('post_type' => 'page','post_parent'=>$parid,'orderby'=>'title','order'=>'ASC' ));

最初のレベルのサブページのみが表示されます。すべてのサブページ、サブのサブページ...、そしてすべてが必要です。私は解決策を探し、get_pagesとwp_list_pagesを使ってすべてのサブページを取得することができます。

しかし、注文の投稿メタ値で注文を並べ替える必要があります。だから私はカスタムクエリを使用する必要があります。

助けてください。ありがとう

12
phpuser

なぜ get_pages() を使わないのですか?

例えば.

<?php
// Determine parent page ID
$parent_page_id = ( '0' != $post->post_parent ? $post->post_parent : $post->ID );
// Get child pages as array
$page_tree_array = get_pages( array(
    'child_of' => $parent_page_id;
) );
?>

しかし、それが本当にWP_Query()オブジェクトでなければならない場合は、同様のメソッドを使用してください。

<?php
// Determine parent page ID
$parent_page_id = ( '0' != $post->post_parent ? $post->post_parent : $post->ID );
// Build WP_Query() argument array
$page_tree_query_args = array(
    'post_parent' => $parent_page_id;
);
// Get child pages as a WP_Query() object
$page_tree_query = new WP_Query( $page_tree_query_args );
?>
6
Chip Bennett

問題

あなたが把握している問題は「どうやってXをするの?」です。これは1ステップではなく、多段階のプロセスであり、分割する必要があります。

これをする必要はありません:

get all the posts that are a child of X ordered by meta

これをする必要があります:

get all the posts that are a child of X
    for each child, get all the posts that are a child
        foreach child of that child get all the posts that are a child
            ...
                hmmm we don't have any more children left

Take our list of posts and order them by meta

一般的な解決策

そのため、ハードコーディングせずに、最後まで無限に実行する方法を理解するには、再帰関数を理解する必要があります。

例えば.

function make_zero( $amount ) {
    $amount = $amount - 1;
    if ( $amount > 1 ){
        return make_zero( $amount );
    }
    return $amount;
}

解決のためにこの問題に再帰を適用する

つまり、あなたの親は$paridであり、あなたの投稿メタは$metakeyのキーを持っています。

その子供たちをつかむために関数にそれを渡しましょう。

$children = get_children_with_meta( $parid, $metakey );

それから、$ children配列をソートします。キーは投稿IDになり、値はメタ値になります。

asort($children);

関数を次のように定義しましょう。

function get_children_with_meta( $parent_id, $metakey ) {
    $q = new WP_Query( array( 'post_parent' => $parent_id, 'meta_key' => $metakey ));
    if ( $q->have_posts() ) {
        $children - array();
        while ( $q->have_posts() ) {
            $q->the_post();
            $meta_value = get_post_meta(get_the_ID(), $metakey, true );
            $children[get_the_ID() ] = $meta_value;
        }
        return $children;
    } else {
        // there are no children!!
        return array();
    }
}

これにより、最低のものから最高のものへと並べられた投稿IDと値の配列が得られます。他のPHPソート関数を使用して、最高から最低へと並べることができます。

今子供はどうですか?

ループの途中で、親IDではなく子を渡して、再帰呼び出しを行う必要があります。

したがって、この:

$q->the_post();
$meta_value = get_post_meta(get_the_ID(), $metakey, true );
$children[get_the_ID() ] = $meta_value;

これになります:

$q->the_post();
$meta_value = get_post_meta(get_the_ID(), $metakey, true );
$children[get_the_ID() ] = $meta_value;

// now get the childrens children
$grandchildren = get_children_with_meta( get_the_ID(), $metakey );

// merge the grandchildren and the children into the same list
$children = array_merge( $children, $grandchildren );

この修正により、関数は子供、子供の子供、子供の子供、子供などを取得します。

最後に、このようなIDを取得するために配列の値を切り捨てることができます。

$post_ids = array_keys( $children );
$q = new WP_Query( array( 'post__in' => $post_ids );
// etc

この方法を使用すると、メタキー値を他のメトリックに置き換えることや、他の方法で再帰関数を使用することができます。

フルコードは、ほんの数秒の基本的な理解と簡単なコピーペーストを必要とするので、フルコピーペーストのコードブロックであなたの知性を侮辱することはできません。

利点

  • 投稿の種類や形式に関係なくデータの修正が可能
  • 入れ子になったマークアップを生成するように変更することができます
  • 返された配列を一時的なものにすることで、高速にキャッシュを簡単に作成
  • ページングを末尾に適用することでページングを設定することができますWP_Query

遭遇する問題

  • あなたが子供を見つけるまで子供の数を知ることはできませんので、パフォーマンスのコストは比例しません
  • あなたが望むものは多くのクエリを生成するでしょう、そして潜在的な深さのために本質的に高価です。

私のおすすめ

ページ階層をフラットにするか、代わりに分類法を使用することをお勧めします。例えば。投稿を評価する場合は、1、2、3、4、5などの用語でページ評価の分類法を使用してください。

または、ナビゲーションメニューを使用して、この問題を完全に回避してください。

4
Tom J Nowell

現在のサブページをすべて再帰的に取得する

これはget_childrenを使った再帰的アプローチです。以下をfunctions.phpに入れてください。

function get_all_subpages($page, $args = '', $output = OBJECT) {
    // Validate 'page' parameter
    if (! is_numeric($page))
        $page = 0;

    // Set up args
    $default_args = array(
        'post_type' => 'page',
    );
    if (empty($args))
        $args = array();
    elseif (! is_array($args))
        if (is_string($args))
            parse_str($args, $args);
        else
            $args = array();
    $args = array_merge($default_args, $args);
    $args['post_parent'] = $page;

    // Validate 'output' parameter
    $valid_output = array(OBJECT, ARRAY_A, ARRAY_N);
    if (! in_array($output, $valid_output))
        $output = OBJECT;

    // Get children
    $subpages = array();
    $children = get_children($args, $output);
    foreach ($children as $child) {
        $subpages[] = $child;

        if (OBJECT === $output)
            $page = $child->ID;
        elseif (ARRAY_A === $output)
            $page = $child['ID'];
        else
            $page = $child[0];

        // Get subpages by recursion
        $subpages = array_merge($subpages, get_all_subpages($page, $args, $output));
    }

    return $subpages;
}

どうやって使うのですか

たとえば、次のように、好きな場所に上記の関数を使用してください。

$all_current_subpages = get_all_subpages(0);

この関数はargsパラメータ(クエリ文字列または配列)とoutput型(上記参照)をサポートしています。

それで、あなたはそれをこんな感じで使うこともできます:

$args = array(
    'post_status' => 'private',
    'order_by' => 'post_date',
    'order' => 'DESC',
);
$all_current_subpages = get_all_subpages(42, $args, ARRAY_A);

そして依存関係get_children => get_posts => WP_Queryのおかげで、この質問の作者によって最初に要求されたように、あなたはメタ値を使うことができます。

3
tfrommen

親ページのすべての子IDを取得する再帰関数を作りました。 IDを取得したら、ページをクエリして、結果をメタキー/値で並べ替えることができます。

// Gets all the children ids of post_parent
function _get_children_ids( $post_parent ) {
    $results = new WP_Query( array(
        'post_type' => 'page',
        'post_parent' => $post_parent
    ) );

    $child_ids = array();
    if ( $results->found_posts > 0 )
        foreach ( $results->posts as $post ) // add each child id to array
            $child_ids[] = $post->ID;

    if ( ! empty( $child_ids ) )
        foreach ( $child_ids as $child_id ) // add further children to array
            $child_ids = array_merge( $child_ids, _get_children_ids( $child_id ) );

    return $child_ids;
}

$children_ids = _get_children_ids( 9 ); // use your numeric page id or get_the_id()

$results = new WP_Query( array(
    'post_type'   => 'page',
    'post__in'   => $children_ids
    #'meta_key'   => 'meta_key', // your meta key
    #'orderby'    => 'meta_key',
    /* 'meta_query' => array( // optional meta_query
        array(
            'key' => 'meta_key', // key
            'value' => array(3, 4), // values
            'compare' => 'IN', // operator
        )
    ) */
) );

var_dump( $results );

階層的にメタキー/値で子をソートする必要がある場合は、(最終のWP_Queryではなく)_get_children_ids関数でmeta_keyおよびorder_byの値をWP_Queryに渡す必要があります。

そうでなければ、すべての子IDを取得するより簡単な方法は次のとおりです。

$children = get_pages( 'child_of=9');

$children_ids = array();
if ( ! empty( $children ) )
    foreach ( $children as $post )
        $children_ids[] = $post->ID;
2
Nicü

これがまさにあなたが求めているものであるかどうかはわかりませんが、wp_list_pages関数を使用して、 'child_of'および 'depth'パラメーターを使用することができます。

詳細については、Codexの次のページを参照してください。 http://codex.wordpress.org/Function_Reference/wp_list_pages

2
Kris Nielsen