2

Not sure if this is possible without some form of hard-coding but I have a custom post-type called 'city'. Within the 'city' post-type I have some parent post (e.g. England, America and China) and some child posts (London, Washington DC and Beijing).

I have a query that displays all of the posts under 'city'. But for this particular query I'd like to actually ignore ANY parent posts (ie. England, America and China) and only display child posts (London, Washington and Beijing).

Here is the way I am coding my query:

<?php $city = new WP_Query(array('post_type' => 'city', 'orderby' => 'name', 'order' => 'ASC', 'posts_per_page' => -1 )); ?>
                            <?php while ($city->have_posts() ) : $city->the_post(); ?>
                                <?php the_title(); ?>
                            <?php endwhile; ?>

So is this possible? I would have thought that doing the opposite is more of a popular question (displaying only the parents and excluding the children) but I'm hoping that my problem is possible!

Thanks

2 Answers 2

1

According to the codex for WP_Query, the solution might be to use the post_parent as the id of the top level post. But as there are a whole lotta top level cpts in your case, I think this solution should help you: How to display only top level posts in loop via WP_Query?.

Update:

<?php
    $all = get_posts(array('post_type'=> 'city', 'posts_per_page' => -1));
    $parents = array();
    foreach ($all as $single)
    {
        $kids = get_children($single->ID);  
        if(isset($kids) && !empty($kids) && count($kids) >= 1)
        {
            $parents[] = $single->ID;
        }
    }

    $args = array('post_type' => 'city', 'orderby' => 'name', 'order' => 'ASC', 'posts_per_page' => -1, 'post__not_in' => $parents );

    $city = new WP_Query($args);
    while ($city->have_posts() ) : $city->the_post();
            echo get_the_title()."<br />";
    endwhile;
    wp_reset_postdata();
?>

This is a long cut, but it works. Just make sure you check if the $parents array is not empty before including it in the query.

13
  • Seems as though there's an error with the solutions code when I paste into my functions.php: The code: Click here
    – remi90
    Commented Dec 19, 2011 at 16:36
  • Did you replace 'my_post_type' with 'city'? Did it for you: pastebin.com/M8LHc5rF Commented Dec 19, 2011 at 17:20
  • Yeh I replaced it already, and I'm talking that code and placing it into my functions.php file - but I get an error (blank white page) on my entire site when I add the code. Is there something else I should be doing in the actual template page's file?
    – remi90
    Commented Dec 19, 2011 at 17:26
  • Nope, there must be a parse error or something. Please turn on the debug mode and check the error. Debug mode: Edit wp-config.php and look for define('WP_DEBUG', false);, change it to to it to define('WP_DEBUG', true);. Save this file and visit the errored page again, you'll know the error. Tell me the error. Commented Dec 19, 2011 at 17:44
  • Notice: Undefined index: aiosp_enabled in /home/farmpro1/public_html/test_server/wtc/wp-content/plugins/all-in-one-seo-pack/all_in_one_seo_pack.php on line 717 Notice: Undefined index: aiosp_enabled in /home/farmpro1/public_html/test_server/wtc/wp-content/plugins/all-in-one-seo-pack/all_in_one_seo_pack.php on line 717 Fatal error: Cannot redeclare my_get_posts() (previously declared in /home/farmpro1/public_html/test_server/wtc/wp-content/themes/WorldTimeClock/functions.php:298) in /home/farmpro1/public_html/test_server/wtc/wp-content/themes/WorldTimeClock/functions.php on line 346
    – remi90
    Commented Dec 19, 2011 at 18:32
1

What you want, I think, is the posts_where filter, which allows you to add additional WHERE clauses to the SQL query that get_posts generates. This will save you the trip to the database to fetch only parent posts.

The hooked function will receive two arguments: the WHERE clause itself and the query object. Check to see if the query is for the city post type, then modify the where clause from there.

<?php
add_filter( 'posts_where', 'wpse29897_no_parents', 10, 2 );
function wpse29897_no_parents( $where, $query )
{
    if( isset( $query->query_vars['post_type'] ) && 'city' == $query->query_vars['post_type'] )
    {
        if( '' != $where )
        {
            $where .= ' AND post_parent !=  0';
        }
        else
        {
            $where .= ' post_parent != 0';
        }
    }
    return $where;
}

I'm guessing that you don't want this to happen for EVERY query that involves the city post type, however. So you best bet is probably to stick the add_filter call right above where you're creating the new WP_Query object. Then stick the wpse29897_no_parents function in your functions.php file or a plugin.

<?php 
add_filter( 'posts_where', 'wpse29897_no_parents', 10, 2 );
$city = new WP_Query(array('post_type' => 'city', 'orderby' => 'name', 'order' => 'ASC', 'posts_per_page' => -1 ));
while ($city->have_posts() ) : $city->the_post(); 
?>
    <?php the_title(); ?>
<?php endwhile; ?>

You could even remove the filter after your loop just to be sure.

<?php remove_filter( 'posts_where', 'wpse29897_no_parents', 10, 2 ); ?>

Not the answer you're looking for? Browse other questions tagged or ask your own question.