1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

How would I mod_rewrite my files so they do not show a .PHP extension in the url?

Discussion in 'Apache' started by Imozeb, May 21, 2010.

  1. #1
    How would I mod_rewrite all of my files so they do not show a .PHP extension in the url?

    Thank you.
     
    Imozeb, May 21, 2010 IP
  2. Namjies

    Namjies Peon

    Messages:
    315
    Likes Received:
    7
    Best Answers:
    0
    Trophy Points:
    0
    #2
    You must create a rewrite rule so your server uses the .php file when someone request a url without .php
    a 2 folders clean url would lool like this:
    RewriteRule ^([^/]+)/([^/.]+)$ index.php?x=$1&y=$2 [L]
    Code (markup):
    ^ = starting delimiter
    [^/] = anything not a dash
    + = 1 or more of previous
    ( X ) = store X element
    [^/.]+ = anything not a dash or dot (so no file extension is picked up)
    $ = end delimter

    add a space then new url to use by the server to fetch the file if a url asked match the previous url format
    index.php?x=$1&y=$2
    $1 = first variable stored by first ( )
    $2 = second variable...
    etc.

    now a url looking like /category/title would use file index.php?x=category&y=title

    you can also create ranges of accepted characters instead of forbidden like [0-9] or [a-z] but since it's clean urls, you'd probably use anything not a dahs and uses folders to split variables apart.

    ~~~~~~~~~~~~~~~~~~

    Next, you need to redirect all the previous urls and change your links on your website:

    e.g.
    RewriteRule ^([^.]+)\.php$ /$1 [R=301,L]
    Code (markup):
    ([^.]+) anything not a dot, stored
    \. escaped dot (dot is a wildcard where any character can replace it, so you have to escape real dots)
    php for extension

    followed by new urls format, /$1 (previous .php file name without extension. the [R=301] final tag instruct to do a 301 redirect

    you can play a bit and create a wide set of rewrite rules and redirects this way.

    Does that help you?
     
    Last edited: May 21, 2010
    Namjies, May 21, 2010 IP
    Imozeb likes this.
  3. joebert

    joebert Well-Known Member

    Messages:
    2,152
    Likes Received:
    88
    Best Answers:
    0
    Trophy Points:
    145
    #3
    Simple answer, use this.

    RewriteCond %{REQUEST_FILENAME}.php -f
    RewriteRule ^(.*[^.]{4,})$ $1.php [L]
    Code (markup):
    A better answer requires a good looking over of your sites files, URL patterns, which version of Apache it's using, etc.
     
    joebert, May 22, 2010 IP
  4. Namjies

    Namjies Peon

    Messages:
    315
    Likes Received:
    7
    Best Answers:
    0
    Trophy Points:
    0
    #4
    shouldn't you avoid -f or -d? just like .*
    not good for CPU usage.
     
    Namjies, May 22, 2010 IP
  5. joebert

    joebert Well-Known Member

    Messages:
    2,152
    Likes Received:
    88
    Best Answers:
    0
    Trophy Points:
    145
    #5
    Where did you hear such a thing ?
     
    joebert, May 23, 2010 IP
  6. Namjies

    Namjies Peon

    Messages:
    315
    Likes Received:
    7
    Best Answers:
    0
    Trophy Points:
    0
    #6
    It was either g1smd or jdMorgan from webmasterworld. They often point out to avoid -f -d checks because they're more CPU extensive. (find the location on the disk just like a normal file request each time).

    RewriteCond %{REQUEST_FILENAME}.php -f will apply to every possible request and make a file check. Which is not needed for plenty of files request.

    /index
    might get checked for index.php existence

    but
    /style.css
    will also be checked for style.css.php existence

    which is just very inefficient on every request for anything if that rule gets applied.

    ~~~~~~~~~~~~~~~~

    They also suggest to avoid .* as often as possible, because it can match any number of any character or nothing. Unless it's a stand alone to redirect all url from domain 1 to domain 2 or anywhere it is inteded to grasp EVERYTHING. Else, depending on your rule complexity, it might end up reworking each request hundreds of time, mostly because at first .* grasps everything, then go back in a trial and error fashion until it match perfectly. Or something close to this. I'd have to refind one of their post.

    Basically, always use rules that can only match what they're inteded for. Like when there as to be something, use + (1 or more)
    Like this rule:
    RewriteRule ^([^/]+)/([^/.]+)$ index.php?x=$1&y=$2 [L]
    it can only match what does not contain slashes, and dots for second part. As such it only picks up domain.com/string/string
    if there's an extension, or no string between slashes like domain.com//test or domain.com/1/test.php no match can occur.
    It should help the server match your urls faster and work less.

    They've answered thousands of post and optimized countless .htaccess files for free. Start learning what they have to tell. It's useful to read their answers. No matter how you write your .htaccess, odds are they can get it even better.
     
    Last edited: May 23, 2010
    Namjies, May 23, 2010 IP
  7. joebert

    joebert Well-Known Member

    Messages:
    2,152
    Likes Received:
    88
    Best Answers:
    0
    Trophy Points:
    145
    #7
    I'm going to go ahead and ignore what you're saying about (.*), you're not telling me anything I don't know there. :)

    The part about skipping -f and -d is something I've never heard anyone suggest before though. "more CPU extensive" than what ?
    I just beat the hell out of the servers I have at home via apache bench, I'm not getting a noticeable difference in the number of requests per second whether I comment out that RewriteCond with the -f flag or not. Sometimes one is faster, other times the other is faster. They both come in at the same average.

    I'm all for making the pattern as specific as possible, but avoiding the -f flag just doesn't make any sense to me.
     
    joebert, May 23, 2010 IP
  8. Imozeb

    Imozeb Peon

    Messages:
    666
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #8
    It is not working...

    .htaccess file
    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^(www.)?foreverplaying.com$
    RewriteRule ^(/)?$ /script/index.php [L]
    RewriteRule ^([^/]+)/([^/.]+)$ index.php?x=$1&y=$2 [L]
    RewriteRule ^([^.]+)\.php$ /$1 [R=301,L]
    Code (markup):
    The first two lines are for a redirect to my homepage. The second two are your code. Do you know why it might not be working?


    I need the rule to make my server read these:
    http://www.foreverplaying.com/script/games/game_blade
    http://www.foreverplaying.com/script/faq
    http://www.foreverplaying.com/script/index

    As these so my server will read the files as .php (this is how they are stored on the server):
    http://www.foreverplaying.com/script/games/game_blade.php
    http://www.foreverplaying.com/script/faq.php
    http://www.foreverplaying.com/script/index.php

    But I need the url in the user's address bar to still read the folder location and file without the .php extension (like the first part). Is this possible?

    Thanks!
     
    Imozeb, May 23, 2010 IP
  9. Namjies

    Namjies Peon

    Messages:
    315
    Likes Received:
    7
    Best Answers:
    0
    Trophy Points:
    0
    #9
    RewriteRule ^([^/]+)/([^/.]+)$ index.php?x=$1&y=$2 [L]
    was just an example of how to build up a rewrite rule.

    Use this in this order:
    RewriteRule ^([^.]+)\.php$ /$1 [R=301,L]
    RewriteRule ^([^.]+)$ $1.php [L]

    RewriteRule ^([^.]+)\.php$ /$1 [R=301,L] should redirect a file like /index.php to /index or /cat/1.php to /cat/1
    RewriteRule ^([^.]+)$ $1.php [L] should make a url like /index use index.php or /cat/1 use /cat/1.php without redirecting.

    You now only have to change your links to be in the new format.
     
    Namjies, May 23, 2010 IP
  10. Namjies

    Namjies Peon

    Messages:
    315
    Likes Received:
    7
    Best Answers:
    0
    Trophy Points:
    0
    #10
    @Joebert
    ask JDmorgan, he'll be able to give you the clearest answer. I'm not too good at .htaccess

    It probably doesn't matter for you and for most people, but If you have lots of traffic, it can make a difference. It might not be seen within your .htaccess file if it's large because of the randomness on each request.

    But compare this:
    RewriteCond %{REQUEST_FILENAME}.php -f
    RewriteRule ^(.*[^.]{4,})$    $1.php [L]
    Code (markup):
    Your condition should try to match style.css to style.css.php or logo.png to logo.png.php and check if these exists, not just try to match clean-url to clean-url.php cause after all, filenames can be multi-extension

    Uneeded file checks.

    With my rewrite:
    RewriteRule ^([^.]+)$   $1.php   [L]
    Code (markup):
    only urls without extensions will trigger the rule and get the .php file. no uneeded file check. and if the .php file to be used by the rewrite is not found, well it will trigger the usual 404. At that point, the file check would have been done anyway, rewrite or not because that's the final file you asked and it was a bad link/typo of the url. Which is usually requests coming from inbound links / typing url in your browser.

    ~~~~~~~~
    Suppose it takes 2 millisecond for the server to go through the files and check if one exists, and you have with a page load 20 different requests (the page, style.css, icons, pictures) and for each of these the rewrite cond check if the filename exist when .php is added to it, you just lost 40 milliseconds in page load time. That would be a good reduction on the amount of pages the server can serve per second.

    I don't know the actual numbers, but I think it's not efficient because for each file check, apache check on the hard drive (not cached version if you actually cache the files. I'm not sure about that, but I think I've read that somewhere that it check on the hard drive. Either way the filecheck was not needed.)

    Most of the time you can just replace the file check with another line which doesn't require it along with processing the condition/rewrite. And that's preferable.

    I might be wrong on some points, but that's what I understand of it. That's why I suggest asking jdMorgan if you want to know accuratly what happens.
     
    Last edited: May 24, 2010
    Namjies, May 24, 2010 IP
  11. joebert

    joebert Well-Known Member

    Messages:
    2,152
    Likes Received:
    88
    Best Answers:
    0
    Trophy Points:
    145
    #11
    RewriteCond never gets evaluated unless the RewriteRule matches the URI. This is why you can reference back-references $1/$2/etc from the RewriteRule in your RewriteCond directives. If you set RewriteLogLevel to 9, it will show you every single step mod_rewrite goes through for each request.

    If you place all of your images/css/js/etc in their own folders, you can use "RewriteEngine Off" in those folders to prevent any rewrites from being applied to those files.
     
    joebert, May 24, 2010 IP
  12. Namjies

    Namjies Peon

    Messages:
    315
    Likes Received:
    7
    Best Answers:
    0
    Trophy Points:
    0
    #12
    Interesting to know, but if it works that way, what's the use of having the file check condition?

    An extensionless url is usually your clean url. If the file for it doesn't exist, it will trigger a 404.
    If you do the file check and it doesn't exists, then there's a second access when the server try to load the extensionless file which will probably end in a 404 too. The extra file check didn't change anything.

    Unless you do use extensionless files with plain text on it, which I doubt, I don't see the point in the file check. I've been told to avoid -f -d, and they do end up being necessary most of the time.

    Unfortunately, I don't have access to the server-level rewriting and can't log the stuff.

    Just out of curiosity, could you explain me this syntax in your rewrite rule?
    (.*[^.]{4,})
    I see in this a stored variable of 0 or any amount of any character .* , followed by something not a dot [^.], and {4,} that's the first time I see something like that. I haven't found what it meant.
     
    Namjies, May 24, 2010 IP
  13. Imozeb

    Imozeb Peon

    Messages:
    666
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #13
    It's still not working. It seems to do an infinite 301 redirect.

    
    RewriteEngine On
    
    RewriteCond %{HTTP_HOST} ^(www.)?foreverplaying.com$
    RewriteRule ^(/)?$ /script/index.php [L]
    
    RewriteRule ^([^.]+)\.php$ /$1 [R=301,L]
    RewriteRule ^([^.]+)$ $1.php [L]
    
    
    Code (markup):
    My real file name as it is on the server: http://www.foreverplaying.com/script/faq.php
    What I typed into the address bar: http://www.foreverplaying.com/script/faq

    Did I do something wrong?
     
    Imozeb, May 24, 2010 IP
  14. looking4vps

    looking4vps Peon

    Messages:
    1,496
    Likes Received:
    6
    Best Answers:
    0
    Trophy Points:
    0
    #14
    It all depends what script you are using and your server configurations
     
    looking4vps, May 24, 2010 IP
  15. joebert

    joebert Well-Known Member

    Messages:
    2,152
    Likes Received:
    88
    Best Answers:
    0
    Trophy Points:
    145
    #15
    Would you rather get a 404 log entry for something that has been rewritten, or for the original request ?
    I would rather get the entry for the original request so I don't have to reverse engineer my logs to find out what's really being requested in the future.

    Just out of curiosity, could you explain me this syntax in your rewrite rule?
    (.*[^.]{4,})
    I see in this a stored variable of 0 or any amount of any character .* , followed by something not a dot [^.], and {4,} that's the first time I see something like that. I haven't found what it meant.
    Code (markup):
    I'll have to dig up the source code for the PERL regular expression library mod_rewrite uses to explain this, one of these days. :)
     
    joebert, May 25, 2010 IP
  16. Imozeb

    Imozeb Peon

    Messages:
    666
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #16
    It's still not working. How can I find the information you need to help me with my problem?
     
    Imozeb, May 25, 2010 IP
  17. Namjies

    Namjies Peon

    Messages:
    315
    Likes Received:
    7
    Best Answers:
    0
    Trophy Points:
    0
    #17
    It's the redirect rule which seems to cause it. But I don't understand why... I'll ask my favorite apache guys at webmasterworld.

    It's probably that the rewrite rule making a url like /index use /index.php instead makes the server also try to redirect because it still use a .php file. I thought the [L] (last rule) after the rewrite would stop the .php used instead of the extensionless file from being reconsidered by the .htaccess and trigger the redirect to extensionless version again in a loop.
    RewriteRule ^([^.]+)\.php$ /$1 [R=301,L]
    RewriteRule ^([^.]+)$ $1.php [L]

    We might have to add a condition before the redirect with THE_REQUEST to check if the url requested by THE BROWSER contains a .php extension. so your rewrited /index to /index.php doesn't try redirect back to /index, which is probably why it creates the loop.

    But I'm sure I've already done this without THE_REQUEST before, but can't find how.

    Edit:Adding this condition just before the redirect should fix it by the way. It was tested successfully on my server.
    
    RewriteCond %{THE_REQUEST} ^[A-Z]+\ [^.]+\.php\ HTTP/
    
    Code (markup):
    I'll be back if there's a way to do it without that condition.
     
    Last edited: May 25, 2010
    Namjies, May 25, 2010 IP
  18. Imozeb

    Imozeb Peon

    Messages:
    666
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #18
    It's not working.

    RewriteCond %{THE_REQUEST} ^[A-Z]+\ [^.]+\.php\ HTTP/
    RewriteRule ^([^.]+)\.php$ /$1 [R=301,L]
    RewriteRule ^([^.]+)$ $1.php [L]

    It won't load still. How can I find any information you need?



    I found this on the web. It isn't working but I was hoping you might be able to take a look at it and see if it might be a solution.

    RewriteCond %{SCRIPT_FILENAME} !-d
    RewriteRule ^([^\.]+)$ $1.php [NC,L]
     
    Last edited: May 26, 2010
    Imozeb, May 26, 2010 IP
  19. kidatum

    kidatum Peon

    Messages:
    61
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    0
    #19
    Golden post, I've been trying to find this for a while now. Thank you.
     
    kidatum, May 26, 2010 IP
  20. Imozeb

    Imozeb Peon

    Messages:
    666
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #20
    Kidatum, what code did you put in your .htaccess? Mine's still not working.
     
    Imozeb, May 27, 2010 IP