The Problem
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
The General Solution
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;
}
Applying Recursion To This Problem For a Solution
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.
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.
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 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