3

My root directory has the following structure:

/assets/ /pages/ /.htaccess index.pp 

Inside /pages/ I have PHP files. For example,projects.php. I tried writing in .htaccess rules to take the URL example.com/projects and open the file from /pages/projects.php and it worked with the following:

RewriteEngine On RewriteCond %{ENV:REDIRECT_STATUS} . [OR] 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}$ /pages/%1.php [NC,L] # All remaining requests simply get rewritten to the subdir RewriteRule (.*) /pages/$1 [L] 

My problem here is that when I go to the root example.com, instead of opening index.php it’s opening the /pages/ directory, but if I go explicitly to example.com/index.php it works.

I don’t want index.php to be shown in the URL, so I need to exclude the root from my rule and make it open index.php while the URL stays example.com.

1
  • "exclude the root from my rule and make it open index.php" - open index.php in the document root or /pages/index.php? Commented Jan 10, 2022 at 12:53

2 Answers 2

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

To exclude "the root" being rewritten to /pages/ (and serve index.php from the root instead) you can simply change the quantifier in the last rule from * (0 or more) to + (1 or more) - so that it doesn't match requests for the root (an empty URL-path in .htaccess).

In other words:

RewriteRule (.+) /pages/$1 [L] 

Incidentally, you have already done something similar in the preceding rule/condition by using + in the CondPattern, ie. RewriteCond %{REQUEST_URI} /(.+).

Sign up to request clarification or add additional context in comments.

Comments

0

I thought about this other solution:

RewriteEngine On RewriteBase / # Hide the "pages" directory and all PHP files from direct access. RewriteRule ^pages\b|\.php$ - [R=404] # Rewrite clean-URL pages to the PHP files inside the "pages" directory: # If the request isn't a file. RewriteCond %{REQUEST_FILENAME} !-f # If the request isn't a folder. RewriteCond %{REQUEST_FILENAME} !-d # If the PHP page file exists. RewriteCond %{DOCUMENT_ROOT}/pages/$0.php -f # /your-page?param=foo is rewritten to /pages/your-page.php?param=foo # The L flag isn't suffisient because the rewrite rule to protect PHP files # above will take over in the second loop over all the rewrite rules. To stop # here we can use the newly END flag which stops completely the rewrite engine. RewriteRule ^.*$ pages/$0.php [END,QSA] 

You wanted to hide index.php. This can be done with a 404 error. So you could just do:

RewriteRule ^index\.php - [R=404] 

But you'll probably want to avoid also someone requesting /pages to list all the PHP files or to directly access /pages/your-page.php. So I used a regex that matches both the directory and PHP file extensions (only lowercase here, but you could use \.(?i)php where (?i) enables the case insensitive flag).

Then, for the rewrite itself, I would capture the URL with ^.*$ which will be available in the $0 backreference which can then be used in the rewrite rule itself and in the rewrite conditions.

If the request is not a directory or an existing file then we have to check that the resulting rewritten URL is effectively an existing PHP file in the pages directory.

I used the QSA flag so that you keep the query parameters in the resulting URL. The PHP script can then access them easily via $_GET. I expect you could also get them by checking some other environment variables if you don't use this flag. I also had to use the END flag which is similar to the L for Last flag but completely stops the rewrite rules to execute. If you use the L flag instead the problem is that you'll get the 404 error due to the fact that /pages/your-page.php will match the rewrite rule to hide PHP files since the whole process of rewrite rules is run a second time. The rewrite engine loop only stops when the input URL doesn't get changed anymore by rewrite rules. Yes, this took me ages to understand that rewrite rules are not just run once like they are displayed in the config file!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.