Skip to main content
Bounty Ended with 50 reputation awarded by jjeaton
added 120 characters in body
Source Link
Tom J Nowell
  • 60.6k
  • 7
  • 77
  • 147

Advantages

  • With modification works for any post type and form of data
  • Can be modified to generate nested markup
  • Easily cache to speed up by putting the returned arrays in transients
  • Can be setup with paging by applying paging to the end WP_Query

Problems You Will Encounter

  • You have no way of knowing how many children there are until you've found them, so performance costs don't scale
  • Paging is going to be costly. You will need to generate a manual list and store it away for later, then apply paging on the very last WP_Query
  • What you want will generate a lot of queries, and is inherently costly because of the potential depths involved.

I would recommend you either flatten your page hierarchy or use a taxonomy instead. E.g. if you're rating posts, Havehave a PostPage Rating taxonomy with the terms 1,2,3,4 and 5 etc. This will provide you with a post listing out of the box.

Alternatively, use nav menus and bypass this problem entirely

Problems You Will Encounter

  • You have no way of knowing how many children there are until you've found them, so performance costs don't scale
  • Paging is going to be costly. You will need to generate a manual list and store it away for later, then apply paging on the very last WP_Query
  • What you want will generate a lot of queries, and is inherently costly because of the potential depths involved.

I would recommend you either flatten your page hierarchy or use a taxonomy instead. E.g. if you're rating posts, Have a Post Rating taxonomy with the terms 1,2,3,4 and 5 etc. This will provide you with a post listing out of the box.

Advantages

  • With modification works for any post type and form of data
  • Can be modified to generate nested markup
  • Easily cache to speed up by putting the returned arrays in transients
  • Can be setup with paging by applying paging to the end WP_Query

Problems You Will Encounter

  • You have no way of knowing how many children there are until you've found them, so performance costs don't scale
  • What you want will generate a lot of queries, and is inherently costly because of the potential depths involved.

I would recommend you either flatten your page hierarchy or use a taxonomy instead. E.g. if you're rating posts, have a Page Rating taxonomy with the terms 1,2,3,4 and 5 etc. This will provide you with a post listing out of the box.

Alternatively, use nav menus and bypass this problem entirely

added 775 characters in body
Source Link
Tom J Nowell
  • 60.6k
  • 7
  • 77
  • 147

The Problem

The General Solution

Applying Recursion To This Problem For a Solution

Since the full code requires only a few seconds of basic comprehension and a quick copy paste, I shan't insult your intelligence with a full copy paste block of code.

Problems You Will Encounter

  • You have no way of knowing how many children there are until you've found them, so performance costs don't scale
  • Paging is going to be costly. You will need to generate a manual list and store it away for later, then apply paging on the very last WP_Query
  • What you want will generate a lot of queries, and is inherently costly because of the potential depths involved.

My Recommendation

I would recommend you either flatten your page hierarchy or use a taxonomy instead. E.g. if you're rating posts, Have a Post Rating taxonomy with the terms 1,2,3,4 and 5 etc. This will provide you with a post listing out of the box.

Since the full code requires only a few seconds of basic comprehension and a quick copy paste, I shan't insult your intelligence with a full copy paste block of code.

The Problem

The General Solution

Applying Recursion To This Problem For a Solution

Since the full code requires only a few seconds of basic comprehension and a quick copy paste, I shan't insult your intelligence with a full copy paste block of code.

Problems You Will Encounter

  • You have no way of knowing how many children there are until you've found them, so performance costs don't scale
  • Paging is going to be costly. You will need to generate a manual list and store it away for later, then apply paging on the very last WP_Query
  • What you want will generate a lot of queries, and is inherently costly because of the potential depths involved.

My Recommendation

I would recommend you either flatten your page hierarchy or use a taxonomy instead. E.g. if you're rating posts, Have a Post Rating taxonomy with the terms 1,2,3,4 and 5 etc. This will provide you with a post listing out of the box.

Source Link
Tom J Nowell
  • 60.6k
  • 7
  • 77
  • 147

What you're having problems grasping is "How do I do X?" This isn't a 1 step action, it's a multistep process, and it needs to be broken apart.

You don't need to do this:

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

You need to do this:

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

So, to understand how to infinitely do it until you reach the end, without hardcoding it, you need to understand recursive functions.

e.g.

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

So your parent is $parid, and your post meta has a key of $metakey.

Lets pass it into a function to grab its children.

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

Then we'll sort the $children array, the keys will be the post IDs, and the values will be the meta values.

asort($children);

and lets define the function as:

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();
    }
}

This gives you an array of post IDs and values, ordered from lowest to highest. You can use other PHP sorting functions to do it from highest to lowest.

Now What About the Childrens Children?

In the middle of our loop, we need to make a recursive call, passing in the child rather than the parent ID.

So this:

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

Becomes this:

$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 );

With this modification the function now retrieves the children, the childrens children, the childrens childrens children..... etc

At the end you can trim off the values on the array to get IDs like this:

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

Using this strategy you can replace the meta key value with any other metric, or use recursive functions in other ways.

Since the full code requires only a few seconds of basic comprehension and a quick copy paste, I shan't insult your intelligence with a full copy paste block of code.