Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am using woocommerce and have some 'product attributes' which are just a taxonomies.

I have the following taxonomies:

  • pa_color
  • pa_material
  • pa_style

the pa_ stands for product attribute and it is built-in to WooCommerce handles these taxonomies, so I can't change that.

WooCommerce also comes with product categories (product_cat) and product tags (product_tag) taxonomies.

the following query gets me all the Red, Vinyl products in the Fabrics product category

?product_cat=fabrics&pa_material=vinyl&pa_color=red

I'd like to turn this into a pretty permalink, something like:

product-category/fabrics/material/vinyl/color/red

This answer gets me pretty close to what I am trying to achieve:

URL rewrite rules for multiple taxonomies query

in that I can get my URL to handle 2 taxonomies (product_cat + 1 attribute taxonomy), but I am stuck on how to get 3 (or more) parameters.

So I can get:

/products-category/fabrics/color/red

or

/product-category/fabrics/material/vinyl

but not all 3 together

/product-category/fabrics/material/vinyl/color/red

edit / though i think it'd be ideal to have the URL be

/fabrics/vinyl/red

i'm not sure that is possible?

end edit/

WooCommerce also has some settings for modifying the permalinks (like prepending the URL with 'shop' or changing the product-category slug) so i'll need to account for that eventually, but right now I need to get this first step down.

for simplicity's sake, this is a stripped down version of my code. I'm actually getting the taxonomies from built-in woocommerce functions, but the question isn't limited to woocommerce... as it pertains to any site w/ a lot of taxonomies.

add_action( 'init', 'wpa_init' );
function wpa_init() {

$taxonomies = array ('pa_color'=>'Color','pa_material'=>'Material','pa_style'=>'Style');
$base = 'product-category';

        foreach ($taxonomies as $taxonomy=>$mask):      
            $attribute = strtolower(sanitize_title($mask));
            add_rewrite_rule( $base.'/(.+?)/'.$attribute.'/([^/]+)(/page/(\d+))?/?$', 'index.php?product_cat=$matches[1]&'.$taxonomy.'=$matches[2]&paged=$matches[4]', 'top' );         
        endforeach;     
}

this was the best resource i've found on taxonomy query permalinks: http://thereforei.am/2011/10/28/advanced-taxonomy-queries-with-pretty-urls/

but it, too, seems stuck at 2 taxonomies.

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

You could try something like this:

function custom_rewrite( $wp_rewrite ) {

    $feed_rules = array(
        'product-category/(.+)/material/(.+)/color/(.+)'    =>  'index.php?product_cat='. $wp_rewrite->preg_index(1).'&pa_material='. $wp_rewrite->preg_index(2).'&pa_color='. $wp_rewrite->preg_index(3)
        'product-category/(.+)/color/(.+)'    =>  'index.php?product_cat='. $wp_rewrite->preg_index(1).'&pa_color='. $wp_rewrite->preg_index(2)
        'product-category/(.+)/material/(.+)'    =>  'index.php?product_cat='. $wp_rewrite->preg_index(1).'&pa_material='. $wp_rewrite->preg_index(2)
    );

    $wp_rewrite->rules = $feed_rules + $wp_rewrite->rules;
}
// refresh/flush permalinks in the dashboard if this is changed in any way
add_filter( 'generate_rewrite_rules', 'custom_rewrite' );

It may not work exactly as advertised, and you might need to do some regex modifications, but that's the general gist of what needs to be done (90% of the work).

You will need to flush the permalinks if you add/edit/remove this code, put it in functions.php or a custom plugin. You can flush permalinks by simply going into the admin area and re-saving the permalinks

As a sidenote, you may run into clashing issues if you start using heirarchies,

e.g. if you have a tshirts/small and a dresses/small category, and you use a URL such as /products-category/small/color/red you might not get the results you expected, e.g. small tshirts? or did you mean small dresses?

So beware of ambiguity

share|improve this answer
    
works pretty well! ideally, i'd like to figure out a way to loop through this so that i don't have to hand-code each new rule. could you explain the difference in matching between: (.+?) ([^/]+) and (.+) ? –  helgatheviking Mar 7 '12 at 19:04
    
They're all regex, the particulars of which I'm not confident enough to answer, but if you find somewhere that explains it well please do link me to it! –  Tom J Nowell Mar 7 '12 at 23:53
    
i still think it's VOODOO! thanks so much for answering... –  helgatheviking Mar 8 '12 at 0:42
    
came back to this- should point out that generate_rewrite_rules is not a filter: it is an action where the parameter is passed by reference –  helgatheviking Mar 18 '12 at 19:25
    
All actions are filters if you look closely enough =p –  Tom J Nowell Mar 19 '12 at 19:48
add comment

For future reference (like next year when I google and find my own question again) this can be converted into add_rewrite_rule() syntax by converting the keys in the $new_rules array into the $regex parameter of add_rewrite_rule() with the value as the $rewrite and 'top' as the $position.

add_rewrite_rule($regex,$rewrite, $position);

Or as an example of one of my requests from above:

function custom_rewrite() {

   add_rewrite_rule(
    'product-category/(.+?)/material/(.+?)/?$',
    'index.php?product_cat=matches[1]&pa_material=$matches[2]',
    'top'
    );

}
// refresh/flush permalinks in the dashboard if this is changed in any way
add_action( 'init', 'custom_rewrite' );

For some reason I was unsuccessful using regenerate_rewrite_rules as a hook/filter so switched to init.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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