Roots Discourse

Query different CPT depending on page


I’m going crazy over how I duplicating the same page template to query specific custom post types. Basically I want to be able to change the CPT slug depending on the page.

So this is the template I want to reuse for several pages without creating template-x.php for each post type.

  <?php $loop = new WP_Query( array( 'post_type' => 'news',
          'posts_per_page' => 100 )
          while ( $loop->have_posts() ) : $loop->the_post(); ?>
        <?php get_template_part('templates/content', 'sage'); ?>

  <?php endwhile; wp_reset_query(); ?>

Can I assign the slug as a variable depending the page? Any other ideas?

Thanks in advance! Can’t sleep over this! :cry:

I might be missing the mark here with what you want but I’d create a custom field to select the post type to show for that page, then use the value of the field within your template to populate your query. You’d then just need a single template to cover all your post types. This is also assuming there a good reason to not use the post type archive?

Thanks for your reply! :slight_smile: I thought of that solution but since it already set what CPU belongs to what page it feels weird? But if I hide the field for all users but me it might be ok.

I need to use pages and not post type archive since the pages are built with a lot of other custom elements. The archive pages is used as well but just as traditional archives.

If you’re just looking to assign the slug as a variable you could try -

$slug = basename(get_permalink());

$args = [
  'post_type' => $slug
  //... etc

Alternately, maybe a function like -

function which_cpt(){
  // get current slug (or you could do ID's)
  global $post;
  $slug = $post->post_name;

  // list of slugs => post types as key/value
  $slugs = [
    'some-page'   => 'some-cpt',
    'another-one' => 'another-cpt'

  // if slug is a key in array, cpt = that keys value, if not return false or something
  array_key_exists($slug, $slugs) ? $cpt = $slugs[$slug] : $cpt = false;

  return $cpt;

That would allow you to not have to match your slugs to your cpt name, which is kind of scary and brittle. (You could alternately us ID’s instead of slugs, which is probably the least scary and brittle of all.) Then in your template -

// use whatever file your function is in
use whatever;
// returns 'some-cpt' on page with slug 'some-slug'
$cpt = whatever\which_cpt();

$args = [
  'post_type' => $cpt,
  // ...etc...

This is a situation-specific solution, but is this for all of, or a majority of your CPTs?

If, for example, you’re doing this for everything but posts, you could single out post with a template slug and let everything else use Sage’s default content and single templates.

At least that way you’re making the smallest number of additional templates. Plus it’s easier to understand just by looking at the template files than having a function somewhere interrupting the template loading process.

Hi guys and a huge thanks for your answers!

Since I already use ACF I went for this solution:

<?php $feed = get_field('article_feed'); ?>
<?php $loop = new WP_Query( array( 'post_type' => $feed,
'posts_per_page' => 100 )

I just made a special loop for the main-feed displaying multiple slugs since I will reuse it as a part under articles.