I have 2 taxonomies and 1 post type:
products
product_cat
product_type
The product-category
has a defined endpoint:
add_endpoint( 'types', EP_PRODUCT_CAT );
Now I'm trying to create a fairly lengthy URL that combines both the taxonomies:
/
Which works, the types
query var is set, the product_cat
is set to what it needs to be too - rainbows and bubblegum.
Pagination. I'm using paginate_links()
which drops my types
query var entirely and assigns it's value to product_cat
query var which results in a 404. The trail begins with add_args
parameter of paginate_links()
. I can pass both product_cat
and types
and pagination works:
global $wp_query;
$term_cat = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
$term_type = get_term_by( 'slug', get_query_var( 'types' ), 'product_type' );
echo paginate_links( array(
'base' => '%_%',
'format' => '?paged=%#%',
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $wp_query->max_num_pages,
'end_size' => 0,
'mid_size' => 2,
'prev_next' => false,
'add_args' => array(
'product_cat' => $term_cat->slug,
'types' => $term_type->slug,
),
) );
So the query_vars are there now but the permalinks are now ugly since paginate_links()
is just appending them as $_GET
parameters:
/?product_cat=abc&types=123
Since the permalink structure is still intact during pagination I'm unsure if rewrite rules will be helpful at this point - but I've given it a try and it doesn't appear to do much at all:
/**
* Endpoints and Rewrites
*
* @return void
*/
function theme_endpoints_rewrites() {
add_rewrite_rule( '^products/([^/]+)/types/([^/]+)/page/([0-9]+)/?', 'index.php?post_type=products&product_cat=$matches[1]&types=$matches[3]&paged=$matches[4]', 'top' );
add_rewrite_endpoint( 'types', EP_PRODUCT_CAT );
flush_rewrite_rules(true);
}
add_action( 'init', 'theme_endpoints_rewrites' );
I've also tried to modify the pagination links URLs to be home_url()
and attempt to rewrite it given the passed arguments but also to no avail. If I leave the permalink structure as Default ( plain
) the pages load as expected. It seems to happen whenever WordPress rewrites the paged
query var.
The below almost works. It shows that product_cat
has the correct / expected value but it concatenates both types
and paged
query vars into 1 value so that my query var holds [types] => cotton/page/2
and drops the paged query var.
function test_rewrites( $wp_rewrite ) {
$wp_rewrite->rules['products/(.+?)/types/(.+?)/page/?([0-9]{1,})/?$'] = 'index.php?product_cat=$matches[1]&types=$matches[2]&paged=$matches[3]';
unset( $wp_rewrite->rules['products/(.+?)/page/?([0-9]{1,})/?$'] );
unset( $wp_rewrite->extra_rules_top['products/(.+?)/page/?([0-9]{1,})/?$'] );
}
add_action( 'generate_rewrite_rules', 'test_rewrites' );
Does anyone know how I can add pagination to the endpoint while keeping my desired URLs?
I have 2 taxonomies and 1 post type:
products
product_cat
product_type
The product-category
has a defined endpoint:
add_endpoint( 'types', EP_PRODUCT_CAT );
Now I'm trying to create a fairly lengthy URL that combines both the taxonomies:
https://www.example.com/products/parent-product-cat/child-product-cat/types/top-product-type/
Which works, the types
query var is set, the product_cat
is set to what it needs to be too - rainbows and bubblegum.
Pagination. I'm using paginate_links()
which drops my types
query var entirely and assigns it's value to product_cat
query var which results in a 404. The trail begins with add_args
parameter of paginate_links()
. I can pass both product_cat
and types
and pagination works:
global $wp_query;
$term_cat = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
$term_type = get_term_by( 'slug', get_query_var( 'types' ), 'product_type' );
echo paginate_links( array(
'base' => '%_%',
'format' => '?paged=%#%',
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $wp_query->max_num_pages,
'end_size' => 0,
'mid_size' => 2,
'prev_next' => false,
'add_args' => array(
'product_cat' => $term_cat->slug,
'types' => $term_type->slug,
),
) );
So the query_vars are there now but the permalinks are now ugly since paginate_links()
is just appending them as $_GET
parameters:
https://www.example.com/products/parent-product-cat/child-product-cat/types/top-product-type/page/2/?product_cat=abc&types=123
Since the permalink structure is still intact during pagination I'm unsure if rewrite rules will be helpful at this point - but I've given it a try and it doesn't appear to do much at all:
/**
* Endpoints and Rewrites
*
* @return void
*/
function theme_endpoints_rewrites() {
add_rewrite_rule( '^products/([^/]+)/types/([^/]+)/page/([0-9]+)/?', 'index.php?post_type=products&product_cat=$matches[1]&types=$matches[3]&paged=$matches[4]', 'top' );
add_rewrite_endpoint( 'types', EP_PRODUCT_CAT );
flush_rewrite_rules(true);
}
add_action( 'init', 'theme_endpoints_rewrites' );
I've also tried to modify the pagination links URLs to be home_url()
and attempt to rewrite it given the passed arguments but also to no avail. If I leave the permalink structure as Default ( plain
) the pages load as expected. It seems to happen whenever WordPress rewrites the paged
query var.
The below almost works. It shows that product_cat
has the correct / expected value but it concatenates both types
and paged
query vars into 1 value so that my query var holds [types] => cotton/page/2
and drops the paged query var.
function test_rewrites( $wp_rewrite ) {
$wp_rewrite->rules['products/(.+?)/types/(.+?)/page/?([0-9]{1,})/?$'] = 'index.php?product_cat=$matches[1]&types=$matches[2]&paged=$matches[3]';
unset( $wp_rewrite->rules['products/(.+?)/page/?([0-9]{1,})/?$'] );
unset( $wp_rewrite->extra_rules_top['products/(.+?)/page/?([0-9]{1,})/?$'] );
}
add_action( 'generate_rewrite_rules', 'test_rewrites' );
Does anyone know how I can add pagination to the endpoint while keeping my desired URLs?
You need to register a post type and two taxonomies for it:
/**
* Register product custom post type and taxonomies
*/
function wp_qhywe2x_register_product_custom_post_type() {
register_post_type( 'product', array(
'label' => __( 'Product', 'text-domain' ),
'labels' => array(
'name' => __( 'Products', 'text-domain' ),
'singular_name' => __( 'Product', 'text-domain' ),
'menu_name' => __( 'Products', 'text-domain' ),
'name_admin_bar' => __( 'Products', 'text-domain' ),
'new_item' => __( 'New Product', 'text-domain' ),
'edit_item' => __( 'Edit Product', 'text-domain' ),
'view_item' => __( 'View Product', 'text-domain' ),
'all_items' => __( 'All Products', 'text-domain' ),
),
'public' => true,
'has_archive' => true,
'rewrite' => array( 'slug' => 'product' ),
'supports' => array( 'title', 'editor', 'thumbnail' ),
'menu_icon' => 'dashicons-cart',
) );
register_taxonomy( 'product_category', array( 'product' ), array(
'hierarchical' => true,
'labels' => array(
'name' => __( 'Product Categories', 'text-domain' ),
'singular_name' => __( 'Product Category', 'text-domain' ),
),
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'product-category' ),
) );
register_taxonomy( 'product_tag', array( 'product' ), array(
'hierarchical' => false,
'labels' => array(
'name' => __( 'Product Tags', 'text-domain' ),
'singular_name' => __( 'Product Tag', 'text-domain' ),
),
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'product-tag' ),
) );
}
add_action( 'init', 'wp_qhywe2x_register_product_custom_post_type' );
In my example, product
post type, and for that, a product_category
and a product_tag
post type.
The necessary settings are already made with the rewrite slug parameter in register_taxonomy()
args, no separate settings are required with any other function.
Then you need a rewrite rule to handle the category and the tag at the same time:
/**
* Product category and tag rewrite rules
*
* @param $wp_rewrite
*/
function wp_qhywe2x_product_category_and_tag_rewrite_rules( $wp_rewrite ) {
$category_rewrite_rules = array();
$product_obj = get_post_type_object( 'product' );
$product_category = get_taxonomy( 'product_category' );
$product_tag = get_taxonomy( 'product_tag' );
/** product category and tag rewrite rule */
$category_rewrite_rules[ $product_obj->rewrite['slug'] . '/' . $product_category->rewrite['slug'] . '/([^/]*)/' . $product_tag->rewrite['slug'] . '/([^/]*)$' ] = 'index.php?post_type=' . $product_obj->name . '&' . $product_category->query_var . '=$matches[1]' . '&' . $product_tag->query_var . '=$matches[2]';
/** pagination rewrite rule - page/1 to ?paged=1 */
$category_rewrite_rules[ $product_obj->rewrite['slug'] . '/' . $product_category->rewrite['slug'] . '/([^/]*)/' . $product_tag->rewrite['slug'] . '/([^/]*)/page/([^/]*)$' ] = 'index.php?post_type=' . $product_obj->name . '&' . $product_category->query_var . '=$matches[1]' . '&' . $product_tag->query_var . '=$matches[2]&paged=$matches[3]';
/** add to wp rewrite rules */
$wp_rewrite->rules = $category_rewrite_rules + $wp_rewrite->rules;
}
add_action( 'generate_rewrite_rules', 'wp_qhywe2x_product_category_and_tag_rewrite_rules' );
This function uses the $product_category->rewrite['slug']
and the $product_tag->rewrite['slug']
, that were set in the register_taxonomy()
function.
Use the following URL structure for the archive page:
http://localhost/product/product-category/plugin/product-tag/awesome/
This will list all products that have a "plugin" category and an "awesome" tag.
If you use the_posts_pagination()
or paginate_links()
function on the archive page, it will display the pagination perfectly, no additional settings are required.