54

I have a problem whereby google has indexed some pages with the wrong url.

The url they are indexing is:

http://www.example.com/index.php/section1/section2

I need it to redirect to:

http://www.example.com/section1/section2

.htaccess isn't my forte, so any help would be much appreciated.

starball
  • 20,030
  • 7
  • 43
  • 238
Nick
  • 715
  • 2
  • 7
  • 10

11 Answers11

90

The original answer is actually correct, but lacks explanation. I would like to add some explanations and modifications.

I suggest reading this short introduction https://httpd.apache.org/docs/2.4/rewrite/intro.html (15mins) and reference these 2 pages while reading.

https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html https://httpd.apache.org/docs/2.4/rewrite/flags.html


This is the basic rule to hide index.php from the URL. Put this in your root .htaccess file.

mod_rewrite must be enabled with PHP and this will work for the PHP version higher than 5.2.6.

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php/$1 [L]

Think %{REQUEST_FILENAME} as the the path after host.

E.g. https://www.example.com/index.html, %{REQUEST_FILENAME} is /index.html

So the last 3 lines means, if it's not a regular file !-f and not a directory !-d, then do the RewriteRule.

As for RewriteRule formats:

enter image description here

So RewriteRule (.*) /index.php/$1 [L] means, if the 2 RewriteCond are satisfied, it (.*) would match everything after the hostname. . matches any single character , .* matches any characters and (.*) makes this a variables can be references with $1, then replace with /index.php/$1. The final effect is to add a preceding index.php to the whole URL path.

E.g. for https://www.example.com/hello, it would produce, https://www.example.com/index.php/hello internally.

Another key problem is that this indeed solve the question. Internally, (I guess) it always need https://www.example.com/index.php/hello, but with rewriting, you could visit the site without index.php, apache adds that for you internally.


Btw, making an extra .htaccess file is not very recommended by the Apache doc.

Rewriting is typically configured in the main server configuration setting (outside any <Directory> section) or inside <VirtualHost> containers. This is the easiest way to do rewriting and is recommended

Rick
  • 7,007
  • 2
  • 49
  • 79
Shakti Singh
  • 84,385
  • 21
  • 134
  • 153
  • thanks so much, one more question - how would I replace hyphens for underscores, ie http://www.mydomain.com/section-1/section-2 to http://www.mydomain.com/section_1/section_2 – Nick Dec 06 '10 at 10:04
  • 8
    If you are really working for SEO no need to convert hyphens to underscores. people are doing just reverse for SEO. Hyphen is google friendly. – Shakti Singh Dec 06 '10 at 10:12
  • 33
    This doesn't remove index.php, instead it adds it! – Calmarius May 06 '14 at 08:17
  • 4
    Those two suggestions are exactly the same? – mnsth Jan 31 '15 at 07:39
  • @mnsth: Search for the hidden `?`. This rule outputs a straight forward 500 status code, with my configuration. –  Mar 04 '15 at 21:37
  • I have php version 5.4.16. But nothing happened with this code. My site is static PHP site with WordPress Blog. Blog url is appending index.php to page links. – Sree May 18 '15 at 09:39
  • 9
    Please explain what you do. 99% people didnt understand what you did in 3 lines. – Pratik Joshi Sep 11 '15 at 02:48
  • 11
    Has the question changed? This solution is adding the index.php to a URL that does not (or does) have it. – Alexandre Nizoux Oct 07 '15 at 09:41
  • 1
    Note: This won't work if you develop locally and you used spaces in your folder name. A folder name like "C:/xampp/htdocs/My TestProject" will result in localhost/My%20TestProject. Solution: remove the spaces from your folder name. ;-) – RWC Nov 29 '17 at 09:29
  • This is only half of what is required. The above code only adds index.php internally to the URL, if index.php is not already there. Thus, if a user enters a URL already containing index.php, the above rule will not remove that index.php from it. Thus, a rule is also needed to "remove" index.php from a URL if it is already present in it. – nvkrj Aug 29 '18 at 17:06
73

To remove index.php from the URL, and to redirect the visitor to the non-index.php version of the page:

RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]

This will cleanly redirect /index.php/myblog to simply /myblog.

Using a 301 redirect will preserve Google search engine rankings.

MrWhite
  • 43,179
  • 8
  • 60
  • 84
Bradley Flood
  • 10,233
  • 3
  • 46
  • 43
21
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.php($|\ |\?)
RewriteRule ^ /%1 [R=301,L]
Steve Bals
  • 1,949
  • 6
  • 22
  • 32
  • I had to add `RewriteRule ^administrator - [L,NC]` to ignore the admin directory – ContextSwitch Jan 28 '14 at 17:19
  • I used this rule for quite some time until I found out it conflicts with other scripts such as Codiad, Afterlogic Webmail Lite or phpSysInfo which need to output `index.php` to the URL. It still works if I add an exception before the first `RewriteCond` like so: `RewriteCond %{REQUEST_URI} !^/mysubfolder`. –  Mar 04 '15 at 21:29
14

Assuming the existent url is

http://example.com/index.php/foo/bar

and we want to convert it into

 http://example.com/foo/bar

You can use the following rule :

RewriteEngine on
#1) redirect the client from "/index.php/foo/bar" to "/foo/bar"
RewriteCond %{THE_REQUEST} /index\.php/(.+)\sHTTP [NC]
RewriteRule ^ /%1 [NE,L,R]
#2)internally map "/foo/bar" to "/index.php/foo/bar"
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ /index.php/$1 [L]

In the spep #1 we first match against the request string and capture everything after the /index.php/ and the captured value is saved in %1 var. We then send the browser to a new url. The #2 processes the request internally. When the browser arrives at /foo/bar , #2rule rewrites the new url to the orignal location.

Amit Verma
  • 40,709
  • 21
  • 93
  • 115
  • Hi mate, can you show me the light? I have issues with mine https://stackoverflow.com/questions/69812175/rewrite-rule-keep-showing-internal-server-error – OneNation Nov 02 '21 at 23:40
14

Steps to remove index.php from url for your wordpress website.

  1. Check you should have mod_rewrite enabled at your server. To check whether it's enabled or not - Create 1 file phpinfo.php at your root folder with below command.
 <?php
   phpinfo?();
 ?>

Now run this file - www.yoursite.com/phpinfo.php and it will show mod_rewrite at Load modules section. If not enabled then perform below commands at your terminal.

sudo a2enmod rewrite
sudo service apache2 restart
  1. Make sure your .htaccess is existing in your WordPress root folder, if not create one .htaccess file Paste this code at your .htaccess file :-
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.php$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.php [L]
</IfModule>  
  1. Further make permission of .htaccess to 666 so that it become writable and now you can do changes in your wordpress permalinks.

  2. Now go to Settings -> permalinks -> and change to your needed url format. Remove this code /index.php/%year%/%monthnum%/%day%/%postname%/ and insert this code on Custom Structure: /%postname%/

  3. If still not succeeded then check your hosting, mine was digitalocean server, so I cleared it myself

Edited the file /etc/apache2/sites-enabled/000-default.conf

Added this line after DocumentRoot /var/www/html

<Directory /var/www/html>
   AllowOverride All
</Directory>

Restart your apache server

Note: /var/www/html will be your document root

Vega
  • 27,856
  • 27
  • 95
  • 103
kandysingh
  • 179
  • 2
  • 6
5

Do the following steps

1. Make sure that the hosting / your pc mod_rewrite module is active. if not active then try to activate in a way, open the httpd.conf file. You can check this in the phpinfo.php to find out.

change this setting :

#LoadModule rewrite_module modules/mod_rewrite.so

to be and restart wamp

LoadModule rewrite_module modules/mod_rewrite.so

2. Then go to .htaccess file, and try to modify to be:

RewriteEngine On

RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)\?*$ index.php/$1 [L,QSA]

if above does not work try with this:

RewriteEngine on

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# otherwise forward it to index.php
RewriteRule . index.php

3. Move .htaccess file to root directory, where is index.php there.

www OR root folder
- index.php
- .htaccess
Kailas
  • 3,173
  • 5
  • 42
  • 52
  • I will appreciate you if you guide me that can i add two rewrite condition is one `.htaccess` file. My htaccess file working properly but i need to rewrite in same file. I want to rewrite this URL (`http://www.example.ae/index.php?route=common/thispage`) to `(http://www.example.ae/thispage)` – Ayaz Ali Shah Mar 09 '16 at 11:27
1

Some may get a 403 with the method listed above using mod_rewrite. Another solution to rewite index.php out is as follows:

<IfModule mod_rewrite.c> 

RewriteEngine On

# Put your installation directory here:
RewriteBase /

# Do not enable rewriting for files or directories that exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]

</IfModule> 
Kyle Coots
  • 2,041
  • 1
  • 18
  • 24
1

I have used many codes from the above mentioned sections for removing index.php form the base url. But it was not working from my end. So, you can use this code which I have used and its working properly.

If you really need to remove index.php from the base URL then just put this code in your htaccess.

RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]

RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
Vega
  • 27,856
  • 27
  • 95
  • 103
0

This will work, use the following code in .htaccess file RewriteEngine On

# Send would-be 404 requests to Craft
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]

Talib Ali
  • 11
  • 3
0

I don't have to many bulky code to give out just a little snippet solved the issue for me.

i have https://example.com/entitlements/index.php rather i want anyone that types it to get error on request event if you type https://example.com/entitlements/index you will still get error since there's this word "index" is contained there will always be an error thrown back though the content of index.php will still be displayed properly

cletus post on "https://stackoverflow.com/a/1055655/12192635" which solved it

Edit your .htaccess file with the below to redirect people visiting https://example.com/entitlements/index.php to 404 page

RewriteCond %{THE_REQUEST} \.php[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]

to redirect people visiting https://example.com/entitlements/index to 404 page

RewriteCond %{THE_REQUEST} \index[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]

Not withstanding we have already known that the above code works with already existing codes on stack see where i applied the code above just below the all codes at it end.

# The following will allow you to use URLs such as the following:
#
#   example.com/anything
#   example.com/anything/
#
# Which will actually serve files such as the following:
#
#   example.com/anything.html
#   example.com/anything.php
#
# But *only if they exist*, otherwise it will report the usual 404 error.

Options +FollowSymLinks
RewriteEngine On

# Remove trailing slashes.
# e.g. example.com/foo/ will redirect to example.com/foo
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=permanent,QSA]

# Redirect to HTML if it exists.
# e.g. example.com/foo will display the contents of example.com/foo.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+)$ $1.html [L,QSA]

# Redirect to PHP if it exists.
# e.g. example.com/foo will display the contents of example.com/foo.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php [L,QSA]

RewriteCond %{THE_REQUEST} \.php[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]

RewriteCond %{THE_REQUEST} \index[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
0

try this, it work for me

<IfModule mod_rewrite.c>

# Enable Rewrite Engine
# ------------------------------
RewriteEngine On
RewriteBase /

# Redirect index.php Requests
# ------------------------------
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteCond %{THE_REQUEST} !/system/.*
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,L]

# Standard ExpressionEngine Rewrite
# ------------------------------
RewriteCond $1 !\.(css|js|gif|jpe?g|png) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]

</IfModule>
ynroot
  • 79
  • 2
  • 8