1

I am lost with rewrite rules and need help please.

I created a custom post type "products" with a custom meta "brand".

The URL for a product called milk will be mysite.com/products/milk, I need the URL include the brand like this, mysite.com/brand-brandname/milk

Some examples: mysite.com/brand-supermilk/milk where "supermilk" is the brand in the custom meta of milk

mysite.com/brand-goodproducts/coffe where good products is the brand

I have this rule and rewrite:

$args = array(
'rewrite' => array('slug' => 'brand-%brand_name%', 'with_front' => false),

);
register_post_type('products', $args);
function wptuts_custom_tags() {
add_rewrite_rule("^brand-([^/]+)?",'index.php?post_type=products&brand_name=$matches[1]','top');

flush_rewrite_rules();

}

add_action('init','wptuts_custom_tags');



 function my_post_type_link_filter_function($post_link, $id = 0, $leavename = FALSE) {
if (strpos('%brand_name%', $post_link) === FALSE) {
    $post = &get_post($id);
    $brand_name =get_post_meta($post->ID,'brand',true);

    if(empty($brand_name)){$brand_name = 'default';}
    $post_link = str_replace('%brand_name%',$brand_name, $post_link);

    return $post_link;


 }
}

add_filter('post_type_link', 'my_post_type_link_filter_function', 1, 3);

All this shows me correct URL in the admin when I add a new product post, but show me 404 or products list of post, but no the product page.

1 Answer 1

5

WordPress seems to be unable to generate the correct rules when you use more complex formats for the slug argument in register_post_type. In this case we have to use add_permastruct.

This example adds the post type and extra rules to enable singular products and brand archives with the correct URLs:

function wpd_products_post_type() {

    // post type args
    // rewrite and has_archive must be true!
    $args = array(
        'public' => true,
        'rewrite' => true,
        'has_archive' => true,
        'supports' => array( 'title', 'custom-fields' ),
    );

    register_post_type(
        'products',
        $args
    );

    // so WP will parse brand_name into query vars
    add_rewrite_tag(
        '%brand_name%',
        '([^&]+)'
    );

    // this sets the actual structure the post type will use
    add_permastruct(
        'products',
        'brand-%brand_name%/%products%',
        array( 'with_front' => false )
    );

    // to enable product archives by brand
    add_rewrite_rule(
        "^brand-([^/]+)?",
        'index.php?post_type=products&brand_name=$matches[1]',
        'top'
    );

}
add_action( 'init','wpd_products_post_type' );

You will still need your post_type_link filter to insert the meta value into the singular product URL.

You will also need to add a pre_get_posts filter for the product archives, to add a meta query for your brand_name.

You could also add an additional pre_get_posts filter for singular products to add in the meta query, as you may discover that you can currently put any value you want in the URL as brand name and the query will succeed, since WordPress only queries for slug by default.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.