Home > Back-end >  Combine several RewriteRule directives into a single rule in .htaccess
Combine several RewriteRule directives into a single rule in .htaccess

Time:10-12

I have the following RewriteRule directives in .htaccess:

RewriteRule ^work/([a-zA-z0-9\-]*).html$ work.php?go=$1 [L]

RewriteRule ^work/([a-zA-z0-9\-]*)/([a-zA-z0-9\-]*).html$ work.php?go=$1&sub=$2 [L]

RewriteRule ^work/([a-zA-z0-9\-]*)/([a-zA-z0-9\-]*)/([a-zA-z0-9\-]*).html$ work.php?go=$1&sub=$2&pid=$3 [L]

RewriteRule ^work/([a-zA-z0-9\-]*)/([a-zA-z0-9\-]*)/([a-zA-z0-9\-]*)/([a-zA-z0-9\-]*).html$ work.php?go=$1&sub=$2&pid=$3&pad=$4 [L]

RewriteRule ^work/([a-zA-z0-9\-]*)/([a-zA-z0-9\-]*)/([a-zA-z0-9\-]*)/([a-zA-z0-9\-]*)/([a-zA-z0-9\-]*).html$ work.php?go=$1&sub=$2&pid=$3&pad=$4&id=$5 [L]

All works fine.

But has anyone an idea, how I can put all this line in only one line as only one rule?

CodePudding user response:

You can't reduce these into a single rule and have it work "exactly" the same. In the single rule all URL parameters will always be defined (but might be empty). With your current set of rules, the URL parameters are only defined if they are required - subtle difference. If you are OK with that slight difference (you should be) then these rules can be reduced into a single rule.

First, I suggest a couple of minor changes to your existing regex:

  • I would assume the final path segment, ie. the "filename" before the .html, is mandatory. Currently, you are allowing /work/.html (which results in an empty go URL parameter).

  • Other URL parameters should accept 1 or more characters, rather than 0 or more. It won't actually "match" 0 characters anyway since multiple contiguous slashes are reduced in the URL-path matched by the RewriteRule pattern.

  • I would simplify the regex you are matching in the path segments. From [a-zA-z0-9\-] to [\w-]. This matches the same as before plus the underscore (_). No need to backslash-escape the literal hyphen when used at the start or end of the character class.

Since you are matching the same pattern in all the path segments, the "combined" rule is not made excessively complex since you can just append another path segment and make it optional for each additional URL parameter (all the preceding path segments must match first). It would, however, be far more complex if you are matching different regex in each path segment - which would involve a lot of nested groups in order to maintain the correct matching order.

Taking the above points into consideration, your 5 rules could be combined into the following single rule:

RewriteRule ^work/([\w-] )(?:/([\w-] ))?(?:/([\w-] ))?(?:/([\w-] ))?(?:/([\w-] ))?\.html$ work.php?go=$1&sub=$2&pid=$3&pad=$4&id=$5 [L]

After the first mandatory path segment (ie. ([\w-] )) the regex (?:/([\w-] ))? is just appended for each additional optional path segment.

Which results in the following rewrites:

  • /work/.html - not rewritten
  • /work/abc.html -> work.php?go=abc&sub=&pid=&pad=&id=
  • /work/abc/def.html -> work.php?go=abc&sub=def&pid=&pad=&id=
  • /work/abc/.html - not rewritten
  • /work/abc/def/ghi/jkl/mno.html -> work.php?go=abc&sub=def&pid=ghi&pad=jkl&id=mno
  • /work/abc/def/ghi/jkl/mno/.html - not rewritten
  • /work/abc/def/ghi/jkl/mno/pqr.html - not rewritten
  • Related