Forum Moderators: phranque

Message Too Old, No Replies

Getting rid of index.php from URL. I can't get it.

I need your help regarding RewriteCond and RewriteRule

         

luismartin

9:34 am on Aug 14, 2012 (gmt 0)

10+ Year Member



I want to get rid of it, but I can't get it working.

I need something like

http://www.example.com/subdirectory/index.php/lang/downloads.html

to be rewritten to

http://www.example.com/subdirectory/lang/downloads.html

This is what I tried:

RewriteCond %{REQUEST_URI} !index\.php
RewriteRule ^subdirectory(\/*)(.*) subdirectory/index.php/$2 [L]


I also tried:

RewriteCond %{REQUEST_URI} !^subdirectory/index\.php
RewriteRule ^subdirectory(\/*)(.*) subdirectory/index.php/$2 [L]


with no success.
Any suggestions are welcome.

lucy24

9:46 am on Aug 14, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I strongly suspect what you really want is the precise opposite of what you and your code say you want. In addition, you probably need at least one thing you don't know you need. Rewrites and Redirects tend to travel in pairs.

Skim through the last half-dozen threads in this Forum, and then when it is no longer 2:45AM someone will come along and see how far you've got.

g1smd

9:51 am on Aug 14, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



NEVER use (.*) in the middle of a RegEx pattern. Use a more "specific" pattern.

Slashes do not need to be escaped.

/* means "" (nothing) or "////////////////" which is probably not what you want.

The first step is to alter the links on the pages of your site to point to the new URLs. URLs are defined in links.

You need a rewrite (using a RewriteRule) to detect the request for the new URL and internally rewrite it to fetch the file on the hardrive that will serve the content. Unless you take steps to avoid it, this type of rule often creates a rewrite loop. This happens because the RegEx pattern matches the rewritten pointer and it is rewritten again. Adding a RewriteCond to exclude requests where index.php is present is usually enough to fix it, but do note that REQUEST_URI needs a leading "/" to match.

The other bit that is missing is that you need a redirect (using another RewriteRule) so that when the old URL is requested the browser is instructed to make a new request for the new URL.

luismartin

10:14 am on Aug 14, 2012 (gmt 0)

10+ Year Member



Thank you both for your replies.

g1smd: Following your advice, I've made the regex more specific now, and I'm not scaping the slashes anymore. No matter to change the links since I'm using Joomla and it changes them automatically.

This is my new try, but still no success:

RewriteCond %{REQUEST_URI} !^/subdirectory/index\.php
RewriteRule ^subdirectory([A-Za-z0-9_\-/]*) subdirectory/index.php/$1 [L]

phranque

10:23 am on Aug 14, 2012 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



i think you're picking up an unintended leading slash in the capture group.

luismartin

11:12 am on Aug 14, 2012 (gmt 0)

10+ Year Member



phranque: you mean the slash before "subdirectory" in the RewriteCond line? g1smd said that REQUEST_URI has a leading slash (in this case that I use ^ to match at the start). Anyway I think I could ignore the match from the beginning and simply do:

RewriteCond %{REQUEST_URI} !index\.php

Could I?

g1smd

11:31 am on Aug 14, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Add the caret back in. It makes the rule run a lot faster. Non-matching requests can be rejected after one or two characters.

I think you're picking up an unintended leading slash in the capture group.

I see that too. Look in the "capture" group. It means that $1 contains a leading slash.

luismartin

11:48 am on Aug 14, 2012 (gmt 0)

10+ Year Member



ok, I see it too, and I'm using the caret again. This is what I have right now:

RewriteCond %{REQUEST_URI} !^/subdirectory/index\.php
RewriteRule ^/subdirectory(/?)([A-Za-z0-9_\-]*) subdirectory/index.php/$2 [L]


I'm still getting a 404 error.

lucy24

7:28 pm on Aug 14, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Can you say in English what you are trying to do? Generally it is something like

"If the user types in A, I want their address bar to say B. Then, when the address bar says B, I want to serve content from material that lives at C."

So what's needed is the values of A, B and C. (A and C may happen to be the same. That's when a {THE_REQUEST} line is crucial.)

luismartin

3:00 pm on Aug 16, 2012 (gmt 0)

10+ Year Member



Can you say in English what you are trying to do? Generally it is something like

"If the user types in A, I want their address bar to say B. Then, when the address bar says B, I want to serve content from material that lives at C."

So what's needed is the values of A, B and C. (A and C may happen to be the same. That's when a {THE_REQUEST} line is crucial.)


ok, let's start again:

The user clicks on a link like this:
http://www.example.com/subdirectory/index.php/lang/downloads.html

It doesn't really matter that the address bar is forced to change in this case (a redirect is not necessary, unless it's necessary to work). I only want this URL to work:
http://www.example.com/subdirectory/lang/downloads.html

The content lives here from the document root:
/subdirectory
downloads.html is not a physical file, nor /lang a physical directory. PHP deals with them once Apache connects the request with index.php

lucy24

10:16 pm on Aug 16, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



OK, now I'm totally confused. Are you trying to add index.php to the middle of an existing URL, or remove an unwanted index.php? Are you talking about links on your own site or on other people's sites? All links on your own sites should point directly to the URL that you want the user to see. Redirects are just for outdated external links or bookmarks.

The URL is what the (human) user sees. It may or may not have anything to do with where the page content lives.


If the URL currently works both with and without "index.php" then a redirect one way or the other will be necessary, because you can't have multiple URLs all serving the same content. That is: physically you can have thousands of URLs all leading to the same place. But for SEO purposes there can only be one.

PHP deals with them once Apache connects the request with index.php

So "index.php" has to be present in the final version as seen by your site. But this by itself doesn't determine the URL, because "index.php" can come from either an internal Rewrite or an external Redirect.

luismartin

11:48 pm on Aug 17, 2012 (gmt 0)

10+ Year Member



No, I want just the opposite, I don't want index.php in the URL in order to get a SEF URL, but as there are external links using the URL with index.php already I have to deal with these requests.

I assume I will need a 301 redirect (moved permanently) from
http://www.example.com/subdirectory/index.php/lang/downloads.html
to
http://www.example.com/subdirectory/lang/downloads.html

And a rewrite from
http://www.example.com/subdirectory/lang/downloads.html
to
http://www.example.com/subdirectory/index.php/lang/downloads.html

which is the URL which PHP can deal with so that index.php is executed, getting the rest of the request uri as PHP parameters.

lucy24

1:45 am on Aug 18, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



OK, good, reassuring, you want The Reasonable Thing ;)

Is the number of subdirectories always the same, as in your example? Or might there be more or less than one before the "index.php" piece? It's definitely easiest if it is always exactly one.

:: thinking ::

The pattern goes like this. First the Redirect:

RewriteCond %{THE_REQUEST} /index\.php/
RewriteRule ^(subdirectory/)index\.php/(lang et cetera) http://www.example.com/$1$2 [R=301,L]

That's for the people who clicked on outdated links. If g1 or someone like him comes along and says the Condition has to be more detailed, pay attention.

And then the internal rewrite:

RewriteRule ^(subdirectory/)(lang et cetera) http://www.example.com/$1index.php/$2 [L]

Is this happening in htaccess? If not, put a slash / at the beginning of each pattern.

If there is only a small number of possible Subdirectories before the "index.php" component, it is fastest to name them:

(directoryone|directorytwo|directorythree)/

If there are lots and lots of them, go to

^([^./]+/)

meaning "exactly one directory, and don't try any funny business with periods in the middle". For the piece after "index.php/" it should be enough to say

([^.]+\.html)

meaning "everything up to the period, and then .html". You need the "/.html" to make sure you don't inadvertently rewrite or redirect requests for images or other non-page material.

Now, if your name is apache dot org and your ordinary URLs happen to include periods along the way, before you ever get to an extension ... Well, I don't want to hear about it.

g1smd

2:07 am on Aug 18, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



One thing to remember is that while the target of a redirect is a URL, the target of a rewrite is an internal filepath without protocol or hostname.

With a rewrite, the address bar in the browser doesn't change.