I have set up the following to create 'pretty' post type and category permalinks:
function kdev_add_category_rules() { $post_types = array( 'kdev_photos', 'kdev_videos', 'kdev_articles' ); foreach($post_types as $post_type) { $pt_obj = get_post_type_object($post_type); $pt_rewrite = $pt_obj->rewrite; $pt_slug = $pt_rewrite['slug']; add_rewrite_rule('^'.$pt_slug.'/category/([^/]*)/?','index.php?post_type='.$post_type.'&category_name=$matches[1]','top'); } } add_action( "init", "kdev_add_category_rules" ); This works great. When I visit sitename.com/photos/category/landscape/ I get all the 'photos' in the 'landscape' category.
Unfortunately, my pagination on these pages is broken.
I would like sitename.com/photos/category/landscape/page/2 to show the second page in this query. Currently it just refreshes the same page. On inspection of the query paged=1.
I've tried the following, but my knowledge of regex is poor.
add_rewrite_rule('^'.$pt_slug.'/category/([^/]*)/page/([^/]*)/?','index.php?post_type='.$post_type.'&category_name=$matches[1]&paged=$matches[2]','top'); What is the correct rewrite rule?
Progress
Interestingly, removing the first 'add_rewrite_rule' allows the new one to work (but obviuosly breaks all the other rewrites). I.e. /photos/category/test-category/page/2/ will work, but /photos/category/test-category/ won't.
EDIT: Additional info
I have refreshed the permalinks loads!
On sitename.com/photos/category/landscape/page/2/, get_query_var('paged') is returning 1.
/category/test-category/page/2/ and /photos/page/2/ both work.
Post types being created using:
// Register Custom Post Type function custom_post_type() { $labels = array( 'name' => _x( 'Photos', 'Post Type General Name', 'text_domain' ), 'singular_name' => _x( 'Photo', 'Post Type Singular Name', 'text_domain' ), 'menu_name' => __( 'Photos', 'text_domain' ), 'parent_item_colon' => __( 'Parent Photo:', 'text_domain' ), 'all_items' => __( 'All Photos', 'text_domain' ), 'view_item' => __( 'View Photos', 'text_domain' ), 'add_new_item' => __( 'Add New Photo', 'text_domain' ), 'add_new' => __( 'New Photo', 'text_domain' ), 'edit_item' => __( 'Edit Photo', 'text_domain' ), 'update_item' => __( 'Update Photo', 'text_domain' ), 'search_items' => __( 'Search photos', 'text_domain' ), 'not_found' => __( 'No photos found', 'text_domain' ), 'not_found_in_trash' => __( 'No photos found in Trash', 'text_domain' ), ); $args = array( 'label' => __( 'kdev_photos', 'text_domain' ), 'description' => __( 'Shared photos', 'text_domain' ), 'labels' => $labels, 'supports' => array( 'title' ), 'taxonomies' => array( 'category', 'post_tag' ), 'hierarchical' => false, 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'show_in_nav_menus' => true, 'show_in_admin_bar' => true, 'menu_position' => 5, 'menu_icon' => '', 'can_export' => true, 'has_archive' => true, 'rewrite' => array( 'slug' => 'photos' ), 'exclude_from_search' => false, 'publicly_queryable' => true, 'capability_type' => 'page', ); register_post_type( 'kdev_photos', $args ); } The site is using the Roots theme which uses Scribu's theme wrapper technique.
The first template called is base.php:
<?php if(is_front_page()) { wp_redirect( get_bloginfo('url').'/photos/', 302 ); exit; } ?> <?php get_template_part('templates/head'); ?> <?php $post_type_query = get_query_var( 'post_type' ); if(!is_array($post_type_query)) $post_type = $post_type_query; ?> <body <?php body_class($post_type); ?>> <?php do_action('get_header'); // Use Bootstrap's navbar if enabled in config.php if (current_theme_supports('bootstrap-top-navbar')) { get_template_part('templates/header-top-navbar'); } else { get_template_part('templates/header'); } ?> <div class="wrap container" role="document"> <div class="content row"> <div class="main <?php echo roots_main_class(); ?>" role="main"> <?php include roots_template_path(); ?> </div><!-- /.main --> <?php if (roots_display_sidebar()) : ?> <aside class="sidebar <?php echo roots_sidebar_class(); ?>" role="complementary"> <div class="well"> <?php include roots_sidebar_path(); ?> </div> </aside><!-- /.sidebar --> <?php endif; ?> </div><!-- /.content --> </div><!-- /.wrap --> <?php get_template_part('templates/footer'); ?> </body> </html> Which then calls index.php:
<?php get_template_part('templates/page', 'header'); ?> <?php $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; ?> <h1>Currently Browsing Page <?php echo $paged; ?></h1> <?php if (!have_posts()) : ?> <div class="alert"> <?php _e('Sorry, no results were found.', 'roots'); ?> </div> <?php get_search_form(); ?> <?php endif; ?> <?php $post_type_query = get_query_var( 'post_type' ); if($post_type_query == 'kdev_photos') $use_grid = TRUE; else $use_grid = FALSE; ?> <?php if($use_grid) echo '<ul class="thumbnails">'; while (have_posts()) : the_post(); if($use_grid) get_template_part('templates/content', 'photo'); else get_template_part('templates/content', get_post_format()); endwhile; if($use_grid) echo '</ul>'; ?> <?php global $wp_query; $big = 999999999; // need an unlikely integer $pag_links = paginate_links( array( 'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ), 'format' => '?paged=%#%', 'end_size' => 1, 'mid_size' => 1, 'current' => max( 1, get_query_var('paged') ), 'total' => $wp_query->max_num_pages, ) ); echo '<div class="pagination">'.$pag_links.'</div>'; ?>
&page=to&paged=? see this question for more information.