Question

I have a Custom Post Type called books. This Custom Post Type has a taxonomy called book_category. As of now, and in the foreseeable future, there are 5 categories each book can be filtered under.

Now, each of these categories have their own respective page that will query the books based on respective category (among other ancillary information pertaining to each category).

In my code below, I made an attempt to query posts based on is_page(). While this DOES work... something is telling me there's a more efficient / proper way of handling this.

<?php
if (is_page('horror')) {
  $theTermBasedOnPage = 'horror';
} elseif (is_page('comedy')) {
  $theTermBasedOnPage = 'comedy';
} elseif (is_page('romantic')) {
  $theTermBasedOnPage = 'romantic';
} elseif (is_page('nonfiction')) {
  $theTermBasedOnPage = 'nonfiction';
} elseif (is_page('drama')) {
  $theTermBasedOnPage = 'drama';
}

$args = array(
  'posts_per_page' => -1,
  'post_type' => 'books',
  'post_status' => 'publish',
  'tax_query' => array(
      array(
          'taxonomy' => 'book_category',

          'terms' => $theTermBasedOnPage,
      ),
  ),
  );
?>

What is the best way to query posts (Custom Post Type > Taxonomy) based on page?

Was it helpful?

Solution

To make that more efficient, instead of arguing the current page slug, you just place the current slug as the tax_query's terms value. Something like:

global $post;
$args = array(
  'posts_per_page' => -1,
  'post_type' => 'books',
  'post_status' => 'publish',
  'tax_query' => array(
      array(
          'taxonomy' => 'book_category',
          'field'    => 'slug',
          'terms'    => $post->post_name, // which'd be `horror` or `comedy`, etc
      ),
  ),
);

Note that there's high probability of human error doing things this way: for example having a page of nonfiction but a book_category term of non-fiction could break the logic and cause problems.

I don't know the context of what you're working on, but if the goal is just "each of these categories have their own respective page" you do not need to build this custom-query-with-manual-page-relation for each term. WordPress taxonomies and terms will have their own URLs if you've registered the taxonomy as public and publicly_queryable. (Guessing here, but) You can probably visit your-site.com/book_category/horror/ and see the list of horror books. You can then customize the template files for all terms or individually using the WordPress template hierarchy as reference.

OTHER TIPS

Custom Taxonomy Pages:

You shouldn't have to create custom query with $args for getting the custom taxonomy pages. You can simply follow WordPress provided URL structure for that.

For example, let's say:

  1. You've selected the following Permalink Structure: enter image description here

  2. Then you've created a custom post type Book

  3. Created custom taxonomy Book Category and linked with Book.

  4. Then created a new Book titled My Horror Story under Horror as Book Category.

  5. And, created another new Book titled My Comedy Story under Comedy as Book Category.

With all the other default settings, WordPress will automatically generate the following URL(s) for you:

// Book Links
https://example.com/book/my-comedy-story/
https://example.com/book/my-horror-story/

// Book Category Links
https://example.com/book-category/comedy/
https://example.com/book-category/horror/

Use these URL(s) for your desired custom taxonomy pages.

Template

Also, you may edit the theme template files to create the desired design. Check out WordPress Template Hierarchy to learn how to do that.

For example, you may create a template file named taxonomy-book-category.php to design Book Category custom taxonomy pages.

In that template file, use WordPress Template Tags and The Loop for necessary queries.

For example, a very simple template file can be like:

<?php
    if ( have_posts() ) : while ( have_posts() ) : the_post();
        the_content();
    endwhile;
    else :
        _e( 'Sorry, no book matched your criteria.', 'textdomain' );
    endif;
?>

Try this:

<?php
// Get post's all terms.
$terms = wp_get_post_terms( get_the_ID(), 'book_category' );

// Get first term ID
$currentPostTermID = $terms[ 0 ]->term_id;

$args = array(
    'posts_per_page' => -1,
    'post_type'      => 'books',
    'post_status'    => 'publish',
    'tax_query'      => array(
        array(
            'taxonomy' => 'book_category',

            'terms' => $currentPostTermID,
        ),
    ),
);
?>
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top