I am trying to remove the sub-folders from my site URL.

Below is the structure of my folders. I am not sure where to place my .htaccess file and what to have written in it:

  • mysiteroot
    • subdir1
    • subdir2
      • index.php
      • page1.php
      • page2.php
      • page3.php

I have written the following:

RewriteEngine On
RewriteRule ^$ subdir1/subdir2/
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule ^(.*)$ subdir1/$1

It seems to only work for the index with my .htaccess file placed in the mysiteroot folder.

How can I make the request for page1.php to show www.mysiteroot.com/page1 instead of www.mysiteroot.com/subdir1/subdir2/page1.php?

2 Answers 2


I had already written most of this before you posted your solution. Posting anyway as a more general solution that readers may find useful.

How can I make the request for page1.php to show www.example.com/page1 instead of www.example.com/subdir1/subdir2/page1.php?

You do this by physically changing the URLs in your application, not in .htaccess. Once the URLs have been changed in your application, the request is then for www.example.com/page1, the visible URL that is shown to your users (not page.php). You then use mod_rewrite in .htaccess to internally rewrite the visible URL back to the real/hidden filesystem path: /subdir1/subdir2/page1.php. (But I suspect you already know this, since your code is doing the right kind of thing.)

In your file hierarchy diagram, you appear to show subdir2 at the same level as subdir1? However, your code and URL structure suggests subdir2 is a subdirectory of subdir1. I'll assume the later.

You basically need to do two things:

  1. Rewrite all requests to /subdir1/subdir2/ (except for requests that map directly to files or directories).

  2. Append the .php file extension to requests that don't already have a file extension.

Try something like the following in the .htaccess file in the document root, ie. mysiteroot/.htaccess.

RewriteEngine On

# If the request has already been rewritten
# Or maps to an existing file then stop here.
# (Can't test for dir here since would not rewrite the doc root)
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]

# No file extension on request then append .php and rewrite to subdir
RewriteCond %{REQUEST_URI} /(.+)
RewriteRule !\.[a-z0-4]{2,4}$ /subdir1/subdir2/%1.php [NC,L]

# All remaining requests simply get rewritten to the subdir
RewriteRule (.*) /subdir1/subdir2/$1 [L]

Any request for /path/to/file (that does not directly map to a file) gets internally rewritten to /subdir1/subdir2/path/to/file.php.

The first RewriteCond directive ensures we don't rewrite requests that have already been rewritten to the subdirectory, thus preventing a rewrite loop.


I found the solution that fit what I wanted to do. Online people provide a generate answer, but the issue is I do not intend to use the same page names without extensions to refer to my pages. This means I keep a file with the list of main pages.

Below are the details of my solution: - Place the htaccess file in my root folder - Refer to the pages in the subdirectories using an absolute reference

htaccess file content:

RewriteEngine On
Options -Indexes #prevents access to folders
RewriteRule ^page1?$ ./subdir2/page1.php
RewriteRule ^page2?$ ./subdir2/page2.php

With this, all the pages in the htaccess will work as if they were in the root dir. So if you are to call a page that is not a main page and is in a sub folder, refer to it at that time going from the root folder

Simple solutions work best at times

  • Thanks for the feedback. Your solution is indeed simpler than your question suggests! However, there are a few things to "check" in the directives you have posted. You probably want to remove the ? in the RewriteRule pattern(s) , eg. ^page1?$. This is a regex, so the ? makes the preceding char optional. This pattern would match "page1" and "page". You should also remove the . (dot) prefix on the RewriteRule substitution (at best it's entirely superfluous). You should include the L flag on your directives. And Apache does not support line-end comments.
    – MrWhite
    Commented Oct 8, 2017 at 23:29

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.