admin管理员组

文章数量:1125893

I currently have the main posts archive page at /blog/ (custom permalink structure of /blog/%postname%/) and categories at /blog/category/ (categories base left empty so it defaults to this).

I have a custom post type of release-notes, which also shares the category taxonomy. The archive page is at /release-notes/, and this works fine along with pagination. It was created with CPT UI, and the only properties I changed were has_archive, with_front and taxonomies, so the $args if created manually should be something like:

  $args = array(
      'public'              => true,
      'has_archive'         => true,
      'exclude_from_search' => false,
      'show_in_rest'        => true,
      'rewrite'             => array( 'slug' => 'release-notes', 'with_front' => false ),
      'taxonomies'          => array( 'category' ),
  );

The issue I'm having is with the pagination on category pages, e.g. /release-notes/category/upgrades/, where pages 2 and beyond return a 404.

To allow for /release-notes/category/upgrades/ (upgrades category of release-notes custom post type) instead of /blog/category/upgrades/ (upgrades category of core post type), which WordPress defaults to, I added a rewrite rule for the URL, and I also added a pre_get_posts to return only release-notes similar to this question.

//Rewrite rule for release notes custom category URL structure
add_rewrite_rule('^release-notes/category/(.+?)/?$', 'index.php?&category_name=$matches[1]&is_release-notes_cat=1', 'top');

//Register is_release-notes_cat query variable
function query_vars( $vars ) {
  array_push($vars, 'is_release-notes_cat');
  return $vars;
}
add_filter( 'query_vars', 'query_vars' );

// Modify main query if is_release-notes_cat page
function set_category_archive_release_notes_posts($query) {
  if (is_category() && isset($query->query_vars['is_release-notes_cat'])) {
      if ($query->is_main_query()) {
          // Set the post type to 'release-notes' only for the main query
          $query->set('post_type', 'release-notes');
      }
  }
}
add_action('pre_get_posts', 'set_category_archive_release_notes_posts');

I'm running the main query in the template file and not a secondary query, so all changes as far as I understand are being made before the query.

      <?php if(have_posts()): ?>

        <div class="release-notes__cards">
          <?php while(have_posts()): the_post();

            get_template_part( 'template-parts/content-release_notes' );

            endwhile;
          ?>
        </div>

        <?php the_posts_pagination(array('class' => 'list--pagination')); ?>

      <?php endif; wp_reset_postdata(); ?>

I'm not sure why it's not working. Any help would be appreciated.

I currently have the main posts archive page at /blog/ (custom permalink structure of /blog/%postname%/) and categories at /blog/category/ (categories base left empty so it defaults to this).

I have a custom post type of release-notes, which also shares the category taxonomy. The archive page is at /release-notes/, and this works fine along with pagination. It was created with CPT UI, and the only properties I changed were has_archive, with_front and taxonomies, so the $args if created manually should be something like:

  $args = array(
      'public'              => true,
      'has_archive'         => true,
      'exclude_from_search' => false,
      'show_in_rest'        => true,
      'rewrite'             => array( 'slug' => 'release-notes', 'with_front' => false ),
      'taxonomies'          => array( 'category' ),
  );

The issue I'm having is with the pagination on category pages, e.g. /release-notes/category/upgrades/, where pages 2 and beyond return a 404.

To allow for /release-notes/category/upgrades/ (upgrades category of release-notes custom post type) instead of /blog/category/upgrades/ (upgrades category of core post type), which WordPress defaults to, I added a rewrite rule for the URL, and I also added a pre_get_posts to return only release-notes similar to this question.

//Rewrite rule for release notes custom category URL structure
add_rewrite_rule('^release-notes/category/(.+?)/?$', 'index.php?&category_name=$matches[1]&is_release-notes_cat=1', 'top');

//Register is_release-notes_cat query variable
function query_vars( $vars ) {
  array_push($vars, 'is_release-notes_cat');
  return $vars;
}
add_filter( 'query_vars', 'query_vars' );

// Modify main query if is_release-notes_cat page
function set_category_archive_release_notes_posts($query) {
  if (is_category() && isset($query->query_vars['is_release-notes_cat'])) {
      if ($query->is_main_query()) {
          // Set the post type to 'release-notes' only for the main query
          $query->set('post_type', 'release-notes');
      }
  }
}
add_action('pre_get_posts', 'set_category_archive_release_notes_posts');

I'm running the main query in the template file and not a secondary query, so all changes as far as I understand are being made before the query.

      <?php if(have_posts()): ?>

        <div class="release-notes__cards">
          <?php while(have_posts()): the_post();

            get_template_part( 'template-parts/content-release_notes' );

            endwhile;
          ?>
        </div>

        <?php the_posts_pagination(array('class' => 'list--pagination')); ?>

      <?php endif; wp_reset_postdata(); ?>

I'm not sure why it's not working. Any help would be appreciated.

Share Improve this question edited Feb 6, 2024 at 2:26 ajs_app asked Feb 5, 2024 at 9:12 ajs_appajs_app 154 bronze badges 2
  • "the permalink structure for categories set to /blog/category/" - what is your permalink structure (for the core post type) - is it blog/%category%/%postname% (which is a Custom Structure)? Or is it %postname%, but the Category base is blog/category? How are you registering the release-notes post type, is it via a plugin? Can you add your post type registration code to your question? – Sally CJ Commented Feb 5, 2024 at 11:02
  • 1 @SallyCJ Sorry, I've updated the question to include the answers to your questions. – ajs_app Commented Feb 6, 2024 at 1:03
Add a comment  | 

1 Answer 1

Reset to default 1

The issue I'm having is with the pagination on category pages, e.g. /release-notes/category/upgrades/, where pages 2 and beyond return a 404.

That's because your custom rewrite rule does not support paged requests, i.e. it's missing the RegEx ( regular expression pattern ) and query for the paged parameter.

So you can either add another rewrite rule which has the above support, or you can use a single RegEx like so:

add_rewrite_rule(
    // I added the (?:/page/(\d+))? which is used to match against the page number.
    '^release-notes/category/(.+?)(?:/page/(\d+))?/?$',

    // I added the &paged=$matches[2] so that WordPress knows what the page number is.
    'index.php?category_name=$matches[1]&is_release-notes_cat=1&paged=$matches[2]',

    'top'
);

The 404 error should now be gone (after flushing the rewrite rules), however, you don't actually have to add the custom query var named is_release-notes_cat.

You could just add &post_type=release-notes to your rewrite rule's query, like so, and WordPress will know that the post type is release-notes when loading your custom category permalink:

add_rewrite_rule(
    // I added the (?:/page/(\d+))? which is used to match against the page number.
    '^release-notes/category/(.+?)(?:/page/(\d+))?/?$',

    // I added the &paged=$matches[2] so that WordPress knows what the page number is.
    // I also removed the &is_release-notes_cat=1 and added &post_type=release-notes.
    'index.php?category_name=$matches[1]&paged=$matches[2]&post_type=release-notes',

    'top'
);

/*
 * If you use the above, then you should remove these parts from your code:
 * add_filter( 'query_vars', 'query_vars' );
 * add_action('pre_get_posts', 'set_category_archive_release_notes_posts');
 */

本文标签: