I got an old project and it has some bizarre issue. Its CodeIgniter project (version 2.X).
Google is indexing our URLs with index.php?. Below is an example
https://www.website.com/index.php?/my-seo-friendly-uri
I can see my pages from above url and with 2 more variants as below
https://www.website.com/index.php/my-seo-friendly-uri
https://www.website.com/my-seo-friendly-uri
We have used https://www.website.com/my-seo-friendly-uri
throughout the site.
My question is how I can redirect https://www.website.com/index.php?/my-seo-friendly-uri
and https://www.website.com/index.php/my-seo-friendly-uri
to https://www.website.com/my-seo-friendly-uri
?
The thing I already did
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^index.php/(.*)$ /$1 [R=302,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>
This redirects index.php
to normal URLs, but index.php?
version of url is still not redirecting
In my config.php
, I have the following settings
$config['index_page'] = '';
$config['uri_protocol'] = 'REQUEST_URI';
2
Answers
This URL contains a query string and so requires a slightly different rule in order to match it. The
RewriteRule
pattern matches against the URL-path only (justindex.php
in this case). The query string is available in its own variable.Add the following, before your existing directives (in addition to the directive that matches
/index.php/my-seo-friendly-url
– which is passed as path-info):The query string is captured (2nd condition), and the backreference (
%1
) is used to construct the redirect.The first condition that checks against the
REDIRECT_STATUS
environment variable is required in order to prevent a redirect loop, since you appear to be using the query string method to route the codeigniter URLs in the later rewrite. TheREDIRECT_STATUS
env var is empty on the initial request, but set to “200” (as in 200 OK HTTP status) after the first successful rewrite.The
QSD
flag (Apache 2.4+) is required to discard the original query string from the redirected request. If you are still on Apache 2.2 then append a?
(empty query string) to the substitution string instead. ie.%1?
By making the match for
index.php
optional (ie.^(index.php)?$
) it will also canonicalise URLs that omitindex.php
, but still include the query string (that may or may not currently be a problem). eg./?/my-seo-friendly-uri
.Note that this is currently a 302 (temporary) redirect (as is your existing redirect). Only change this to a 301 (permanent) redirect once you have confirmed it works OK. 301s are cached persistently by the browser so can make testing problematic.
Summary
Your
.htaccess
file should look like this:Additional notes…
<IfModule>
wrapper is not required.(.*)
is the same as^(.*)$
since regex is greedy by default./index.php/foo
) to also redirect requests for/index.php
only. This now requires an additional condition to avoid a redirect loop.Your CodeIgniter front-controller is using the query string method to pass
/my-seo-friendly-url
to the backend (as used in the question). However, you have set$config['uri_protocol'] = 'REQUEST_URI';
– which contradicts with this (although shouldn’t necessarily be a problem). However, if you are using theREQUEST_URI
method then you can remove the?/$1
part from the end of the finalRewriteRule
substitution string. For example:For example, from this:
To this:
Use .htaccess…………….