Custom Taxonomy Endpoint Pagination using paginate_links()

admin2025-01-07  3

The Setup

I have 2 taxonomies and 1 post type:

  • Post Type: products
  • Hierarchical Taxonomy: product_cat
  • Nonhierarchical Taxonomy: 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.

The Issue

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?

The Setup

I have 2 taxonomies and 1 post type:

  • Post Type: products
  • Hierarchical Taxonomy: product_cat
  • Nonhierarchical Taxonomy: 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.

The Issue

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?

Share Improve this question edited Jun 20, 2017 at 19:42 Howdy_McGee asked Jun 20, 2017 at 17:00 Howdy_McGeeHowdy_McGee 20.8k24 gold badges91 silver badges175 bronze badges 3
  • 1 Did you ever find a solution for this? – davemackey Commented Jan 25, 2018 at 20:24
  • 1 @davemackey Sorry, I never did - I think we ended up doping the permalink structure and going with something simplified. – Howdy_McGee Commented Jan 25, 2018 at 20:31
  • 1 have you tried the reverse aproach? Adding an endpoint category to the existing endpoint product-types and see if the paginate links are retained in the types query var? – Aurovrata Commented Dec 1, 2020 at 15:30
Add a comment  | 

1 Answer 1

Reset to default 0

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.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1736260564a674.html

最新回复(0)