Home  >  Q&A  >  body text

htaccess rewrite rules not working after migrating to php 8

<p>After migrating from PHP 7 to PHP 8, I ran into an issue with url rewrite rules. </p> <p>On top of htaccess I have the following code</p> <pre class="brush:php;toolbar:false;">Options FollowSymLinks RewriteEngine on RewriteBase /baba/ ErrorDocument 404 http://localhost/baba/404.php</pre> <ol> <li>Search page:-</li> </ol> <p>It works great if I just use the following rule: -</p> <pre class="brush:php;toolbar:false;">RewriteRule ^s/([\w-] )/(.*)$ search.php?feq=$1&key=$2 [QSA,L ]</pre> <p>But if I add more rules like below then these pages will give 404. </p> <pre class="brush:php;toolbar:false;">RewriteRule ^s/([\w-] )/(.*)/(.*)$ search.php?feq=$1&city= $2&key=$3 [QSA,L] RewriteRule ^s/([\w-] )/(.*)/(.*)/(.*)$ search.php?feq=$1&pro=$2&city=$3&key=$4 [ QSA,L]</pre> <ol start="2"> <li>Landing page:-</li> </ol> <p>It works great if I just use the following rule: -</p> <pre class="brush:php;toolbar:false;">RewriteRule ^([\w-] )$ land.php?name=$1 [QSA,L]</pre> <p>But if I add more rules like below, the css and images stop loading on other pages and those pages give 404. </p> <pre class="brush:php;toolbar:false;">RewriteRule ^([\w-] )/(.*)/(.*)$ land.php?name=$1&pro=$2& ;city=$3 [QSA,L] RewriteRule ^([\w-] )/(.*)$ land.php?name=$1&key=$2 [QSA,L] RewriteRule ^([\w-] )/(.*)/(.*) land.php?name=$1&city=$2&key=$3 [QSA,L] RewriteRule ^([\w-] )/(.*)/(.*)/(.*)$ land.php?name=$1&pro=$2&city=$3&key=$4 [QSA, L]</pre></p>
P粉274161593P粉274161593319 days ago342

reply all(1)I'll reply

  • P粉022501495

    P粉0225014952023-09-02 09:45:36

    This has nothing to do with PHP version - your rules are clearly conflicting...

    Because the regex in the first rule is too general (it matches /s/foo/), if you simply add the second rule, the first rule still All requests will be captured and rewritten as search.php?feq=foo&key= regardless of the number of path segments. You need to be more specific with regular expressions. For example, to only match the entire path segment, not literally any:

    RewriteRule ^s/([\w-]+)/([^/]*)$ search.php?feq=&key= [QSA,L]
    
    RewriteRule ^s/([\w-]+)/([^/]+)/([^/]*)$ search.php?feq=&city=&key= [QSA,L]
    RewriteRule ^s/([\w-]+)/([^/]+)/([^/]+)/([^/]*)$ search.php?feq=&pro=&city=&key= [QSA,L]

    Please note [^/] (anything except /) instead of . (anything). You can also use (1 or more) in mandatory path segments.

    As with your original rule, the key URL parameters (i.e. the second path segment in the first rule and the last path segment in subsequent rules) are optional. Is this intentional?

    If you know the characters allowed in these URL parameters, you should indicate these characters in the regular expression to further restrict the URL, otherwise it will be (incorrectly) rewritten.

    You can also reverse the order of the instructions to solve the problem at hand, but this is only a partial solution since your regex is still too generic.

    As mentioned above. However, CSS and image failures may be caused by using relative URL paths for these resources in client-side HTML. You are rewriting the request from a different path depth, so you must use the root relative (or absolute) URL of the static resource. Relative URLs are naturally resolved (by the browser) relative to the URL in the browser's address bar.

    (As a workaround, you can set the base element in the head section to indicate that all relative URLs are relative to the base URL path relative to, but this is not without caveats.)

    Further reading on lost assets:

    Also note that your "Landing Page" rule must come after your "Search Page" rule, otherwise they will also conflict. Again, this conflict can be avoided by making the regular expression more specific. For example, avoid conflicts with # by setting the first path segment in the "Landing Page" (the value of the name URL parameter) to 2 or more characters instead of 1 or more characters. ##/conflicts/ (in Search).


    Narration:

    This triggers a 302 (temporary) redirect to your 404 error document (which masks the 404 response and the URL that actually triggered the 404). This is generally not advisable unless you have very specific requirements. You should typically use a root-relative URL path here. For example:

    ErrorDocument 404 /baba/404.php

    /baba/404.php is then served via an internal subrequest, and the error document itself is not exposed to the end user.

    If you are using Redirects to resolve missing resource issues, see above about not using relative URLs in HTML source code.

    reply
    0
  • Cancelreply