Search code examples
.htaccessmod-rewriteurl-rewriting

Different .htaccess rewrite rules for new directory


My .htaccess currently has the following behaviour using the rewrite rules below:

https://example.com/abcd?lol=true

  • if file /abcd.php exists, open https://example.com/abcd.php?lol=true
  • if directory and file /abcd/index.php exist, open https://example.com/abcd/index.php?lol=true
  • else open https://example.com/index.php?lol=true

-> in all three cases the address bar must still show https://example.com/abcd?lol=true

RewriteEngine On

RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1%{REQUEST_URI} [R=301,QSA,NC,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]

RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [END]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ / [END]

Now to my question: I have a new directory /blog/, where the following must happen:

https://example.com/blog/abcd?lol=true

  • open https://example.com/blog/index.php?lol=true

-> the address bar must still show https://example.com/blog/abcd?lol=true so I can use php to read the abcd part, which could be an article name.

How can I append my .htaccess code to achieve this?


Solution

  • Aside: You're not actually doing anything for #2 (ie. "if directory and file /abcd/index.php exist...") - you are probably relying on default behaviour by mod_dir. However, if you request /abcd?lol=true and /abcd exists as a physical directory, there will be a 301 external redirect to append the trailing slash (ie. /abcd/?lol=true ) which will then result in /abcd/index.php being served. So, this does not strictly show /abcd?lol=true in the address bar as you suggest. Is that what you are seeing?


    To implement the /blog/abcd?lol=true to /blog/index.php?lol=true rewrite then replace your last rule with the following:

    # Prevent further processing if a file or directory is requested directly
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [END]
    
    # Route requests to blog/index.php
    RewriteRule ^blog/. blog/index.php [END]
    
    # Everthing else is routed to "/index.php"
    RewriteRule . index.php [END]
    

    This separates out the filesystem checks into their own rule so you aren't doing this twice.


    Your previous "last" rule:

    RewriteRule ^(.*)$ / [END]
    

    You were only rewriting to / and then relying on mod_dir issuing an internal subrequest for index.php (the DirectoryIndex). You should instead rewrite directly to index.php as required (no need for the slash prefix). The capturing pattern ^(.*)$ is unnecessary here.