Redirect all to index.php using htaccess
Your rewrite rule looks almost ok.
First make sure that your .htaccess
file is in your document root (the same place as index.php
) or it'll only affect the sub-folder it's in (and any sub-folders within that - recursively).
Next make a slight change to your rule so it looks something like:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]
At the moment you're just matching on .
which is one instance of any character, you need at least .*
to match any number of instances of any character.
The $_GET['path']
variable will contain the fake directory structure, so /mvc/module/test
for instance, which you can then use in index.php to determine the Controller and actions you want to perform.
If you want the whole shebang installed in a sub-directory, such as /mvc/
or /framework/
the least complicated way to do it is to change the rewrite rule slightly to take that into account.
RewriteRule ^(.*)$ /mvc/index.php?path=$1 [NC,L,QSA]
And ensure that your index.php
is in that folder whilst the .htaccess
file is in the document root.
Alternative to $_GET['path']
(updated Feb '18 and Jan '19)
It's not actually necessary (nor even common now) to set the path as a $_GET
variable, many frameworks will rely on $_SERVER['REQUEST_URI']
to retrieve the same information - normally to determine which Controller to use - but the principle is exactly the same.
This does simplify the RewriteRule
slightly as you don't need to create the path parameter (which means the OP's original RewriteRule
will now work):
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L,QSA]
However, the rule about installing in a sub-directory still applies, e.g.
RewriteRule ^.*$ /mvc/index.php [L,QSA]
The flags:
NC
= No Case (not case sensitive, not really necessary since there are no characters in the pattern)
L
= Last (it'll stop rewriting at after this Rewrite so make sure it's the last thing in your list of rewrites)
QSA
= Query String Append, just in case you've got something like ?like=penguins
on the end which you want to keep and pass to index.php.
.htaccess for redirect all requests to index.php
This is the .htaccess I use
RewriteEngine On
# The following rule tells Apache that if the requested filename
# exists, simply serve it.
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
# The following rewrites all other queries to index.php. The
# condition ensures that if you are using Apache aliases to do
# mass virtual hosting, the base path will be prepended to
# allow proper resolution of the index.php file; it will work
# in non-aliased environments as well, providing a safe, one-size
# fits all solution.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]
Also, do not use relative links anywhere! href="img/some-image.jpg"
should be changed to href="/img/some-image.jpg"
.
Give that a try.
.htaccess - Redirect All URLs + Existing Directories to index.php
The error is with this RewriteRule
RewriteRule /sub/directory/index\.php - [L]
See What is matched?
- In per-directory context (Directory and .htaccess), the Pattern is matched against only a partial path, for example a request of "/app1/index.html" may result in comparison against "app1/index.html" or "index.html" depending on where the RewriteRule is defined.
and "Per-directory Rewrites":
- The removed prefix always ends with a slash, meaning the matching occurs against a string which never has a leading slash. Therefore, a Pattern with ^/ never matches in per-directory context.
This means, the leading slash prevents the pattern from matching. Changing it to
RewriteRule ^sub/directory/index\.php - [L]
will fix the problem.
The 500 Internal server error comes from the second rule (in combination with the non-matching first rule).
RewriteRule ^.*$ /sub/directory/index\.php
This will rewrite any request to /sub/directory/index.php
, which in turn will be rewritten again to /sub/directory/index.php
, and so on until the rewrite module gives up and shows a "too many redirects" error or similar.
Use htaccess file to redirect all traffic to index.php and non-www to www
Yes, there is. First of all keep your original rule as it was (slightly modified, see below):
RewriteEngine On
RewriteCond %{HTTP_HOST} !=www.example.com
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
After that, add:
RewriteCond %{HTTP_HOST} =www.example.com
RewriteRule ^(.*)$ index.php?path=$1 [QSA]
So very similar to what you already had, except:
- removing flags on the last rule that weren't necessary
- adding a check for the host on the second rule
- removing slash on replacement in second rule that is not part of the match in a .htaccess file
- changing the RewriteCond check a little, including redirecting anything that is not www.example.com rather than just example.com. I recommend pointing ww.example.com and similar to your site so spelling mistakes like that get redirected with it (personally I just point *.example.com to my site in most cases).
Let me know any problems.
.htaccess Redirect all html files to index.php
Add this rule
RewriteRule ^(.*)$ /index.php?$1 [L]
.htaccess: ??/index.php -- ??/, built on a relative path
To serve index.php
from the requested directory you use mod_dir's DirectoryIndex
directive (which is probably already set in the server config, although defaults to index.html
only) - you do not need mod_rewrite for this. For example:
# Serve "index.php" from the requested directory
DirectoryIndex index.php
This instructs Apache to serve index.php
from whatever directory is requested. eg. Request /foo/bar/
then /foo/bar/index.php
is served via an internal subrequest (no redirect). If index.php
is not present in that directory you'll get a 403 Forbidden response (assuming directory listings - as generated by mod_autoindex - are disabled).
To remove index.php
from any URL that is requested directly you can use mod_rewrite. For example:
RewriteEngine On
# Remove "index.php" from any URL and redirect back to the "directory"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.php(/|$) /$1 [R=301,L]
The above will redirect as follows, preserving the requested protocol and hostname:
/index.php
to/
/foo/index.php
to/foo/
/foo/bar/index.php
to/foo/bar/
/fooindex.php
- NO REDIRECT (404 expected)/foo/index.php/bar
(containing path-info) to/foo/
(path-info removed)/foo/index.phpbar
- NO REDIRECT (404 expected)
The (optional) capturing group (.*/)?
contains the part of the URL-path before index.php
. This is then available in the substitution string using the $1
backreference. In the case when /index.php
is requested in the document root, this is empty. When a subdirectory is present then this contains a string of the form subdir/
, including the trailing slash.
If you have no other directives in your .htaccess
file then you don't strictly need the condition that checks against the REDIRECT_STATUS
environment variable. This condition ensures that only direct requests are redirected in the case when you have a front-controller pattern later in the file that might rewrite requests to index.php
.
If you do have other directives in the file then the order can be important. This rule that removes index.php
via an external redirect must go before any existing rewrites, near the top of the file.
Note that this removes index.php
from the URL regardless of whether the requested URL actually maps to a real file or whether the preceding URL-path even exists as a physical directory. So, /<something>/index.php
is redirected to /<something>/
regardless of whether /<something>/
is a physical directory or not. This check can be implemented at the cost of an additional filesystem check - but it's probably not required.
NB: Test first with a 302 (temporary) redirect to avoid potential caching issues. Only change to a 301 (permanent) redirect once you have tested that it works as intended.
UPDATE#1:
These Questions do not provide an answer:
htaccess redirect index.php to root (including subdomains)
- This does not address subdirectories, only subdomains
- This redirects
example.tld/dir/index.php
toexample.tld/
, but I needexample.tld/dir/
Actually, the first question you've linked to does answer your question, with regards to removing index.php
from the requested URL. It does address subdirectories and would redirect example.tld/dir/index.php
to example.tld/dir/
(not example.tld/
as you've stated).
The part of the question that discusses subdomains is a bit misleading as it doesn't really have anything to do with subdomains specifically.
The solution presented in the linked question basically does the same sort of thing as I've done above, except that it arguably matches too much (and not enough). It would incorrectly/unnecessarily redirect /fooindex.php
to /foo
(no trailing slash) and would fail to redirect URLs that contained path-info (which could be malicious). eg. /foo/index.php/bar
would fail to redirect but still serve the contents of /foo/index.php
(unless AcceptPathInfo
had been disabled). Although whether these "errors" would actually cause an issue in your case is another matter.
UPDATE#2:
I have the code exactly in the directory for
example.tld/dir
The code above assumes the .htaccess
file is located in the document root. If the .htaccess
file is located in the directory of where the app is installed then you would need to modify the above like so:
# Remove "index.php" from any URL and redirect back to the "directory"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} ^/(.+/)?index\.php
RewriteRule (^|/)index\.php(/|$) /%1 [R=301,L]
The %1
backreference (as opposed to $1
) refers to the captured group in the preceding CondPattern. This naturally includes the full URL-path, so avoids having to hardcode the directory in which the .htaccess
file is located.
This applies to the directory that contains the .htaccess
file and any subdirectories thereof. Note that, by default, this completely overrides any mod_rewrite directives that might be present in the parent .htaccess
file (mod_rewrite directives are not inherited by default).
...including subdirectories, which may have their own .htaccess and index.php.
If additional sub-subdirectories have their own .htaccess
file then this may or may not work depending on the directives used in these sub-subdirectory .htaccess
files and/or how mod_rewrite inheritance is configured.
mod_rewrite directives do not inherit by default. So, if the .htaccess
file in the sub-subdirectory enables the rewrite engine then the above mod_rewrite directives in the parent directory will be completely overridden (they are not even processed).
If, on the other hand, the .htaccess
file in the sub-subdirectory uses directives from other modules then this may not be an issue.
Redirect all links in a Folder to index.php with GET variable(using htaccess)?
The documentation that comes with the apache http server's rewriting module is of excellent quality and comes with great examples. You will also find the answer to your question in there.
You will probably want to tweek this to your specific needs, but the following should point you into the correct direction:
RewriteEngine on
RewriteRule ^/?folder/(.*)$ /index.php?file=$1 [END,QSA]
In case you receive an internal server error (http status 500) using the rule above then chances are that you operate a very old version of the apache http server. You will see a definite hint to an unsupported [END]
flag in your http servers error log file in that case. You can either try to upgrade or use the older [L]
flag, it probably will work the same in this situation, though that depends a bit on your setup.
This rule will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT
folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).
.htaccess need help to serve requests to index.php in non root folder
On the face of it, this just looks a standard front-controller pattern. Whether the front-controller is located inside a subdirectory or directly in the document root is largely irrelevant - the process is the same.
Assuming you are using the .htaccess
file in the document root and there is no discernable pattern to the page URLs...
For example, using mod_dir FallbackResource
:
FallbackResource /pages/index.php
Or, using mod_rewrite:
DirectoryIndex /pages/index.php
RewriteEngine On
RewriteRule (^|/)index\.php - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . pages/index.php [L]
UPDATE#1:
It's "onepage" website format with plenty of JS and CSS. There are only local URLs pointing to sections (href tag) and AJAX call to specific PHP files
In that case, it just looks like you need to change the DirectoryIndex
- you don't need a front-controller pattern (as discussed above) at all.
For example:
DirectoryIndex /pages/index.php
Now, a request for the "homepage", ie the document root https://example.com/
will serve /pages/index.php
.
UPDATE#2:
From your screenshot, it looks like directory listings (mod_autoindex) are enabled. These should be disabled at the top of the .htaccess
file:
Options -Indexes
UPDATE#3:
From your screenshot, it would seem that what you have called "root" in your file structure is not actually your website's "document root", since you are accessing this location via a /test
subdirectory, ie. localhost/test/
. The directives above are assuming these files are located in the "document root", ie. localhost/
and there is no /test
subdirectory. (Which I expect is how it is structured on your "live" environment?)
If your .htaccess
file is located in the /test
subdirectory and you are requesting localhost/test/
(as per your screenshot) then you will need to adjust this accordingly:
For example:
DirectoryIndex /test/pages/index.php
However, that will not work on the live site (assuming you don't have a /test
subdirectory on live). Instead, you can simply omit the slash prefix, to make it relative.
For example:
DirectoryIndex pages/index.php
This should work OK in your case since you have a SPA (just a homepage URL).
Related Topics
Is There a Use-Case For Singletons With Database Access in PHP
How to Call a JavaScript Function from PHP
Fatal Error: Maximum Execution Time of 30 Seconds Exceeded
Check If PHP Session Has Already Started
How to Remove Duplicate Values from an Array in PHP
How to Add Elements to an Empty Array in PHP
If Block Inside Echo Statement
Mvc For Advanced PHP Developers
PHP $_Post Array Empty Upon Form Submission
Detect Browser Language in PHP
PHP Pass by Reference in Foreach
Access a JavaScript Variable from PHP
PHP File_Get_Contents() and Setting Request Headers
How to Get an Array of Specific "Key" in Multidimensional Array Without Looping