Support » Developing with WordPress » Custom query using one category that is used in all custom post types

  • I need some help from someone who can look at the code template below and see what I apparently still have wrong. I’ve been working on getting a template setup for a site that is using TwentyTwelve as its base. This template would call up all post types but using only a common single category. I thought I had it nailed in tests two years ago, but the client is now getting around to using it and reports that it isn’t working.

    An answer that someone else gave was to use this in the args:

    $args = array(
          'post_type' => 'any', //or use cpt slug as string, or array of strings if multiple
          'category_name' => 'budgeting', // <-- EDIT CATEGORY SLUG HERE. Must be all lower case and with dashes if there are any, exactly as it appears in the category listings. Be careful not to delete the single quotes!
        );

    Example: A template that uses the category of “budgeting” shows 24 posts, and the site has 20 regular posts and 6 of another post type using that same category. So it seems to be working because it is showing more than 20 posts. The template:

    <?php
    /**
     * Template Name: Category - Budgeting
     *
     * ^^^ THIS IS THE TEMPLATE TITLE THAT APPEARS IN THE DROPDOWN ON A PAGE EDITING AREA. KEEP THE ASTERISKS.
     *
     * The template for displaying all pages.
     *
     * This is the template that displays all pages by default.
     * Please note that this is the WordPress construct of pages
     * and that other 'pages' on your WordPress site will use a
     * different template.
     *
     * @package WordPress
     * @subpackage Twenty_Twelve
     * @since Twenty Twelve 1.0
     */
    
    get_header(); 
    
        $args = array(
          'post_type' => 'any', //or use cpt slug as string, or array of strings if multiple
          'category_name' => 'budgeting', // <-- EDIT CATEGORY SLUG HERE. Must be all lower case and with dashes if there are any, exactly as it appears in the category listings. Be careful not to delete the single quotes!
        );
    
        // This query should now only have the post_type in the args above.
        $this_query = new WP_Query( $args ); ?> 
    
    <div id="primary" class="site-content">
        <div id="content" role="main">
    
        <?php 
        if ( $this_query->have_posts() ) : ?>
                <header class="archive-header">
                    <h1 class="archive-title">
                    <?php
                    if ( is_day() ) :
                        printf( __( 'Daily Archives: %s', 'twentytwelve' ), '<span>' . get_the_date() . '</span>' );
                        elseif ( is_month() ) :
                            printf( __( 'Monthly Archives: %s', 'twentytwelve' ), '<span>' . get_the_date( _x( 'F Y', 'monthly archives date format', 'twentytwelve' ) ) . '</span>' );
                        elseif ( is_year() ) :
                            printf( __( 'Yearly Archives: %s', 'twentytwelve' ), '<span>' . get_the_date( _x( 'Y', 'yearly archives date format', 'twentytwelve' ) ) . '</span>' );
                        else :
                            _e( 'Budget Articles List', 'twentytwelve' ); // <-- EDIT THE PAGE TITLE HERE. BE CAREFUL NOT TO EDIT THE SINGLE QUOTE MARKS!!!
                        endif;
                    ?>
                    </h1>
                </header><!-- .archive-header -->
    
            
    
           <?php while ( $this_query->have_posts() ) : $this_query->the_post(); 
                $post_id = get_the_ID(); // In case you need to use the post ID
                ?>
    
                <?php if( has_post_thumbnail() ): ?>
            <header class="entry-header">
                
                <h1 class="entry-title">
                    <a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?></a>
                </h1>
                <span class="post-meta">Author  <?php the_author_posts_link(); ?> | <?php the_time('F jS, Y'); ?>  | <?php the_category(', '); ?></span>
                
            </header><!-- .entry-header -->
    
                  <div class="entry-summary">
                <a href="<?php the_permalink(); ?>"><?php the_post_thumbnail('thumbnail', array('class' => 'alignleft')); ?></a><?php the_excerpt(); ?>
            </div><!-- .entry-summary -->
    
                <?php endif; ?>
    
            <?php
            endwhile;
            
            wordpress_numeric_post_nav();
    
            wp_reset_postdata();
        endif;
        ?>
        </div><!-- #content -->
    </div><!-- #primary -->
    
    <?php get_sidebar(); ?>
    <?php get_footer(); ?>

    When we try this with another category of “College Education”, there are 8 regular posts and 4 of another post type in the system with ‘college-education’ as the slug. But only 8 posts show up in the page when the template is used with that slug in place. We should be seeing twelve posts. So this isn’t working.

    Could someone advise me if you see something that shouldn’t work? We thought we had nailed this but it’s not working.

    Link for the Budget page on the actual site: https://moneysmartfamily.com/budget-articles-list/

    Link for the College Education page on the actual site: https://moneysmartfamily.com/college-education-articles-list/

    The page I need help with: [log in to see the link]

Viewing 8 replies - 1 through 8 (of 8 total)
  • Joy

    (@joyously)

    This is not at all what a template file is supposed to do, and you will have problems with pagination, because that is not handled in the standard rewrite rules.
    The template file should simply output what WP has already queried. If you want to mix posts and other post types in one category, use the pre_get_posts filter to change the post type to any instead of doing your own query. This should be in the plugin where the post type is defined and the category taxonomy is added to the custom post type.

    Trying to do a multi-post query on a Page is problematic because of the pagination, which uses the main query’s global variables.
    If you want more content on a category page, you can use the category description to hold it. (there are plugins for rich editing for descriptions)
    Then you make your category template output the description, usually only on the first page. You can make templates specific to a category by naming it according to the Template Hierarchy, if you want to, but it’s usually not needed.

    Hi Joy, thanks for the reply. Are you saying that it’s not possible to do this? I’m not interested in having a description on a category template, because we just want to have all the common-category posts showing up in a single archive listing.

    We’re using MetaBox to add the custom post types, and there are taxonomies created for each post type. We edited the taxonomies to be the same slugs on all five types (regular posts and the four custom post types), so we’d be using identical slugs. That’s why the query that was suggested to me seemed simple and obvious to use “post_type” as “any” and “category_name” as the particular slug we wanted to query.

    I’m reading the pre_get_posts documentation in the codex, and I see that it’s a function that gets added to change the parameters of a query.

    So if I’m understanding this, am I able to write a single function that would change the query under the conditions if it’s a particular category? That would seem to be a good idea if it knows that when a few particular categories are used, those would create the query needed and place that in the archive template. And if it’s a plug-in, it can be used as a catch-all without having to resort to multiple custom templates based on the number of categories needed. It could be one file that needs to be adapted for category listings if we add more categories. Am I correct that a conditional function could be written to say, “if the category chosen is from [array of chosen categories], show the posts from all post types that use that category’s slug”. Could it be that simple?

    Joy

    (@joyously)

    Yes, it could be that simple.
    I was mentioning about the category description just because I didn’t know why you needed a specific template to show a category. Your URL looks like a Page, and you were using a Page template, so the main query is for a Page. The parsing of the query distinguishes between singular and multiple (archive), so that paging can be handled. That’s why it’s difficult to put an archive on a Page and have pagination work right.

    I haven’t tried the filter to change the post type, but in a way, it seems like you wouldn’t even need it if you defined the taxonomies correctly with the post types, not just changing the slug but associating the post type with the taxonomy. https://developer.wordpress.org/reference/functions/register_taxonomy_for_object_type/
    You would need to try it.

    Yes it was a page that was used, and I didn’t realize that pagination would be an issue, but now I see it. Thanks so much for pointing out something that I didn’t understand, now I see that the page method is doomed. I’ll look into what you shared.

    I do have custom taxonomies tied in with those custom post types, but there is also a check box in MetaBox for assigning the default taxonomies to the custom post types, now I wonder if that will automatically take care of the problem. See, when I see this site up a few years ago with the custom post types, there wasn’t the idea of having them all tie together with common categories. But they wanted this later, so now I’m wondering if just setting those CPTs to have the default taxonomy would take care of the issue. We did edit the custom taxonomies to have the same slugs now, but if I set the taxonomies to default, then they would be the same, wouldn’t they? Then wouldn’t all post types get called up together in a basic category call-up?

    Joy

    (@joyously)

    Yes, it seems like it would, but it probably depends on what the plugin is doing when you check the box for the CPT to have the default taxonomy.
    Maybe if you look in the admin category page, and check the count, and I think you can click on it to see what is listed, to make up that count. (But then again that might not work since Categories is under Posts, and so it might just be showing Posts there.)

    That’s exactly what I was thinking: wondering what MetaBox is doing when default categories are checked. Only one way to find out: try it.

    Moderator bcworkz

    (@bcworkz)

    The docs say the post type query var defaults to “any” when “tax_query” is used, but I’ve not found that to be the case. I’ve always had to explicitly set the post type when I want other types besides “post”. The counts on the category list table only reflect posts, my CPTs are not included, even when accessing the table through my CPT admin menu item.

    I would just let the default category term request be handled by WP as it normally would, but I’d modify the query through “pre_get_posts” action. Verify that the current query is the main query. Then use WP_Query::is_category() to determine if the request is for any of the targeted terms. If so, set the “post_type” query var to “any”.

    Thanks bcworkz, for taking the time to comment. My client is going to try using default categories in the next few days and will get back to me. It sounds like I might need to write a plug-in function with pre_get_posts to force through what you’re suggesting. So I’ll put this into consideration if we’re heading in that direction.

Viewing 8 replies - 1 through 8 (of 8 total)
  • You must be logged in to reply to this topic.