admin管理员组

文章数量:1122832

For a certain Wordpress shop with woocommerce we need the url to display the category id (term_id) instead of the normal slug with the category name. So instead of www.website/categoryname/ it needs to display www.website/?term_id=12 and then still display the right category.

So far I have come up with this:

function add_custom_query_vars_filter( $vars ){
    $vars[] = "term_id";
    return $vars;
}
add_filter( 'query_vars', 'add_custom_query_vars_filter' );

// Modify the main query based on term_id
function modify_main_query_based_on_term_id( $query ) {
    if ( !is_admin() && $query->is_main_query() && isset( $query->query_vars['term_id'] ) && is_numeric( $query->query_vars['term_id'] ) ) {
        $term_id = intval( $query->query_vars['term_id'] );
        $term = get_term( $term_id, 'product_cat' );

        if ( $term && ! is_wp_error( $term ) ) {
            $query->set( 'product_cat', $term->slug );
            $query->is_archive = true;
            $query->is_tax = true;
            $query->is_product_category = true;
            $query->queried_object = $term;

            // Setting the necessary globals for WooCommerce
            global $wp_query;
            $wp_query->is_archive = true;
            $wp_query->is_tax = true;
            $wp_query->is_product_category = true;
            $wp_query->queried_object = $term;
            $wp_query->queried_object_id = $term_id;
        }
    }
}
add_action( 'pre_get_posts', 'modify_main_query_based_on_term_id' );

// Ensure the correct template is loaded
function load_woocommerce_category_template_based_on_term_id( $template ) {
    if ( get_query_var( 'term_id' ) ) {
        $term_id = intval( get_query_var( 'term_id' ) );
        $term = get_term( $term_id, 'product_cat' );

        if ( $term && ! is_wp_error( $term ) ) {
            // Use WooCommerce's built-in template loader
            $template = wc_get_template_part( 'archive', 'product' );
        }
    }
    return $template;
}
add_filter( 'template_include', 'load_woocommerce_category_template_based_on_term_id' );

Regretfully it will not use the category template from woocommerce like this, like we want to.

Does anybody have a solution that might work?

For a certain Wordpress shop with woocommerce we need the url to display the category id (term_id) instead of the normal slug with the category name. So instead of www.website.com/categoryname/ it needs to display www.website.com/?term_id=12 and then still display the right category.

So far I have come up with this:

function add_custom_query_vars_filter( $vars ){
    $vars[] = "term_id";
    return $vars;
}
add_filter( 'query_vars', 'add_custom_query_vars_filter' );

// Modify the main query based on term_id
function modify_main_query_based_on_term_id( $query ) {
    if ( !is_admin() && $query->is_main_query() && isset( $query->query_vars['term_id'] ) && is_numeric( $query->query_vars['term_id'] ) ) {
        $term_id = intval( $query->query_vars['term_id'] );
        $term = get_term( $term_id, 'product_cat' );

        if ( $term && ! is_wp_error( $term ) ) {
            $query->set( 'product_cat', $term->slug );
            $query->is_archive = true;
            $query->is_tax = true;
            $query->is_product_category = true;
            $query->queried_object = $term;

            // Setting the necessary globals for WooCommerce
            global $wp_query;
            $wp_query->is_archive = true;
            $wp_query->is_tax = true;
            $wp_query->is_product_category = true;
            $wp_query->queried_object = $term;
            $wp_query->queried_object_id = $term_id;
        }
    }
}
add_action( 'pre_get_posts', 'modify_main_query_based_on_term_id' );

// Ensure the correct template is loaded
function load_woocommerce_category_template_based_on_term_id( $template ) {
    if ( get_query_var( 'term_id' ) ) {
        $term_id = intval( get_query_var( 'term_id' ) );
        $term = get_term( $term_id, 'product_cat' );

        if ( $term && ! is_wp_error( $term ) ) {
            // Use WooCommerce's built-in template loader
            $template = wc_get_template_part( 'archive', 'product' );
        }
    }
    return $template;
}
add_filter( 'template_include', 'load_woocommerce_category_template_based_on_term_id' );

Regretfully it will not use the category template from woocommerce like this, like we want to.

Does anybody have a solution that might work?

Share Improve this question asked Jun 10, 2024 at 11:59 MartinMartin 11 bronze badge
Add a comment  | 

2 Answers 2

Reset to default 0

Try this. Here is the full code that you can add to your functions.php file:

// Add custom rewrite rules
function add_custom_rewrite_rules() {
    add_rewrite_rule(
        '^category/([0-9]+)/?$',
        'index.php?term_id=$matches[1]',
        'top'
    );
    flush_rewrite_rules(false); // Temporarily set this to true to flush rules, then set back to false
}
add_action('init', 'add_custom_rewrite_rules');

// Add term_id to query vars
function add_query_vars($vars) {
    $vars[] = 'term_id';
    return $vars;
}
add_filter('query_vars', 'add_query_vars');

// Redirect to the correct category page
function custom_category_redirect() {
    if (get_query_var('term_id')) {
        $term_id = intval(get_query_var('term_id'));
        $term = get_term_by('id', $term_id, 'product_cat');
        if ($term) {
            $url = get_term_link($term, 'product_cat');
            if (!is_wp_error($url)) {
                wp_redirect($url, 301);
                exit;
            }
        }
    }
}
add_action('template_redirect', 'custom_category_redirect');

// Flush rewrite rules when necessary
// Note: Remember to remove this line after the first load to prevent unnecessary flushing
flush_rewrite_rules(true);

Important Notes:

  • Rewrite Rules and Permalinks: Be cautious when modifying rewrite rules and flushing them. Flushing rewrite rules too frequently can affect site performance.

  • Permanent Redirects: The wp_redirect function with a 301 status code is used to permanently redirect the URL. If you intend this to be a temporary change, consider using a 302 status code instead.

  • Testing: Thoroughly test this code in a staging environment before applying it to a live site to ensure it doesn't interfere with other functionality.

By following these steps, you will be able to change the category URL structure to use term_id and still display the correct category page in WooCommerce.

Thanks @Quang but this didn't work for me either. After getting another theme and creating a childs theme I could easily do what I wanted like this:

add_action('init', 'custom_rewrite_rules');
add_filter('request', 'handle_custom_permalink');
add_filter('post_type_link', 'custom_product_permalink', 10, 2);
add_filter('term_link', 'custom_woocommerce_category_link', 10, 3);
add_filter('query_vars', 'add_custom_query_vars');

// Initialize custom hooks
function custom_rewrite_rules() {
    add_rewrite_rule('^p=([0-9]+)/?', 'index.php?p=$matches[1]&post_type=product', 'top');
    flush_rewrite_rules();
}

// Handle custom permalinks
function handle_custom_permalink($query_vars) {
    if (isset($query_vars['p']) && !isset($query_vars['post_type'])) {
        $post_id = $query_vars['p'];
        if (get_post_type($post_id) === 'product') {
            $query_vars['post_type'] = 'product';
        }
    } elseif (isset($query_vars['c']) && is_numeric($query_vars['c'])) {
        $c = intval($query_vars['c']);
        $term = get_term($c, 'product_cat');
        if ($term && !is_wp_error($term)) {
            $query_vars['product_cat'] = $term->slug;
        }
    }
    return $query_vars;
}

// Custom product and category permalinks
function custom_product_permalink($permalink, $post) {
    if ($post->post_type === 'product') {
        return home_url('?p=' . $post->ID);
    }
    return $permalink;
}

function custom_woocommerce_category_link($url, $term, $taxonomy) {
    if ('product_cat' === $taxonomy) {
        return home_url('?c=' . $term->term_id);
    }
    return $url;
}

// Add custom query vars
function add_custom_query_vars($vars) {
    $vars[] = "c";
    return $vars;
}

本文标签: categoriescategory id (termid) in url instead of slug