0

I have the following rewrite rule to handle when all arguments are present:

add_action('init', 'ebd_custom_rewrite_rules');
function ebd_custom_rewrite_rules() {
    add_rewrite_rule('^shop-region/(.*)/engine-work/(.*)/machining-capability/(.*)/engine-specialty/(.*)/application-specialty/(.*)/dyno-facility/(.*)?', 'index.php?shop-region=$matches[1]&engine-work=$matches[2]&machining-capability=$matches[3]&engine-specialty=$matches[4]&application-specialty=$matches[5]&dyno-facility=$matches[6]', 'top');
}

Sometimes one or more of these arguments is not present. I am looking a way for it to handle when any 2 arguments are present, any 3 arguments are present, any 4 arguments are present and any 5 arguments are present in addition to when all are present. Is there a way to do this without writing 56 additional rewrite rules?

2
  • Why would it be 56?
    – Tom J Nowell
    Mar 28 at 15:35
  • Selecting any 2 would be 15 combinations, selecting any 3 would be 20 combinations, selecting any 4 would be 15 combinations, selecting any 5 would be 6 combinations. Given that they will always be in the same order.
    – Tommizzy
    Mar 28 at 15:51

2 Answers 2

2

I was able to make this work by using a power set function and then using that array to create individual rewrite rules.

add_action('init', 'ebd_custom_rewrite_rules');
function ebd_custom_rewrite_rules() {
    $taxonomies = array( 'engine-work', 'engine-specialty', 'application-specialty', 'machining-capability', 'dyno-facility', 'shop-region');
    $combinations = ebd_get_array_power_set($taxonomies);
    $element_size_min = 2;
    foreach ($combinations as $combination) {
        if ($element_size_min <= count($combination)) { // skip singles - already defined by taxonomy
            $regex = '^'; //init regex string
            $query = 'index.php?'; //init query string
            $number_of_slugs = 1; //keep track of the index we're on
            foreach (array_reverse($combination) as $taxonomy_slug) { //array_reverse to preserve order
                $regex .= $taxonomy_slug.'/(.*)/'; //add taxonomy to regex
                $query .= $taxonomy_slug.'=$matches['.$number_of_slugs.']&'; //add taxonomy to query
                $number_of_slugs++; //increase count
            }
            $regex = substr($regex, 0,strrpos($regex,'/')).'?'; //remove last slash
            $query = substr($query, 0,strrpos($query,'&'));//remove last ampersand
            add_rewrite_rule($regex, $query, 'top');
        }
    }
}

function ebd_get_array_power_set($array) {
    $results = array(array( ));

    foreach ($array as $element)
        foreach ($results as $combination)
            array_push($results, array_merge(array($element), $combination));

    return $results;
}

Power Set Ref.

1

No but not because of WP rules, it's because you'd need to write a single regular expression that matched any URL that met your parameters, and map it into a singular URL. While you could figure out a regex, now the matches no longer have predictable numbers, making the second URL that takes the form index.php?.... impossible to write.

Instead, it would be easier to create all of the independent rewrite rules. Luckily PHP is a programming language so you can assemble the rules automatically, you don't need to do it individually by hand. Instead of writing each regex by hand, do it in code and generate the output.

E.g.

$regex = '^' . $param_one . $param_two;
add_rewrite_rule( ....

Where $param_one is '/engine-work/(.*) and $param_two is /machining-capability/(.*), filled in using logic/loops/arrays. Now it's no longer a WordPress problem, or a regex problem, but a generic programming problem.

As a start, you may want to define an array of all the arguments and their regex pieces, e.g.:

$pieces = [
    'shop_region' => 'shop-region/(.*)'`
    etc...
1
  • Thank you for your advice. I was afraid I was going to need to resort to this. You helped me solve the issue.
    – Tommizzy
    Mar 28 at 18:33

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.