Recent Topics

Remove ".php" from your blogs (advanced stuff)

Started by on Jun 17, 2004 – Contents updated: Jun 17, 2004

Jun 17, 2004 01:23    

For those of you who think that "clean urls" just aren't clean enough, here's a way that you can strip off the ".php" from all your blog pages quite easily.

Requirements:
1. Apache, and with the mod_rewrite module. (If you're not sure about this, ask your host. But, if you do what's in here, and get huge major errors, then you probably don't have it.)
2. Use extra path info. (If you've got Apache, and it's installed, why not?)
3. Access to your .htaccess file. (Again, if you're not sure about this, ask your host.)
4. Set up your blog display method as "other blog through stub file."
5. Set up your stub files on your server, and get that all working. For the purposes of this tutorial, the filename will be "blog.php," but you can name it whatever you want. They should all have a ".php" extension.

Once that's all done...

Now, we're going to be accessing your blog with permalinks this:
http://your.site.com/blog/2004/06/16/url_title
In order to be able to tell the server when to treat "blog" as a folder, and when to treat it as a php file, you'll need to come up with a list of all the folders that should be accessible from the URL. (A side benefit of this is that, any folders that should NOT be accessed directly will result in a big fat 404, since the php file won't be found!)

Open up in a text editor the .htaccess from your root blog folder, or create one if it's not already there.
Type this in it:

Code

RewriteEngine On
Save and upload the file, and go back to your site.

Still works? Great! (If not, you're not going to get any further. Undo what ya did, and tell your host that you want mod_rewrite.)

Open up your .htaccess file again, and make it say this:

Code

RewriteEngine On
# enter all the allowed folder names separated by |s
RewriteCond %{REQUEST_URI} !^/(admin|gettext|htsrv|images|img|media|skins)(.*)$
RewriteRule (^[^\./]+)$ $1\.php
 
# enter the same list of folder names here
RewriteCond %{REQUEST_URI} !^/(admin|gettext|htsrv|images|img|media|skins)(.*)$
RewriteRule (^[^\./]+)/(.+)$  $1\.php/$2
In plain english, the first rule says, "If the user asks for 'foo', and 'foo' is not one of these allowed folders, then give them 'foo.php' instead." The second rule says, "If the user asks for foo/bar/1/2/3, and 'foo' is not in this list of allowed folders, give them foo.php/bar/1/2/3 instead." If the user types in a folder that is not in your "allowed" list, even if the folder exists, they'll get a 404 error telling them that "disallowed_folder.php does not exist."

Now, manually type in the new .php-less url, and make sure that it works. (If you get an "Error 500: Internal Server Error," then you probably mistyped something, or you might not have permission to do what you're doing here. Check your work, and/or talk to your host. They might have an error log with more info.)

Make sure that you can still get to the backoffice.

If everything checks out, then go into the backoffice in b2evolution, and remove the ".php" from the stub name of all your blogs. Make sure that the Permalink Style is set to "url title", because that's the most streamlined of the permalinks.

Enjoy :)

[PS] There is a way to do this by checking to see if the first part of the request is a valid folder/file, and only rewriting if it will succeed. However, I haven't figured out how to do that yet, and I kinda dig only allowing access to certain folders. Any mod_rewrite gurus in the house are encouraged to show me up by posting an even better way to do this! :)

Jun 17, 2004 01:48

Kewl :)

How about listing the stub files you want to rewrite instead of the folders you don't want to ? Might be easier on maintainance... any reason not to do this? (apart from digging the 404s :P)

Jun 17, 2004 01:56

Hm... Apart from digging the 404s, no, no difference at all. Change the RewriteCond lines to look like this:

Code

RewriteCond %{REQUEST_URI} ^/(stub1|stub2|etc)(.*)$
Like I said, I'm sure there's a way to use the -d and -f flags to test before rewriting, which would be the easiest set of rules to maintain, since there'd be nothing hard coded at all. I haven't cracked that one, yet, tho.

Jun 17, 2004 07:44

Works real nice!

I don't understand it all, especially why there are two rules with the same condition, but it works!

I'm just a little bit annoyed by three details personnaly:
1) it won't work on sub/ with nothing after the / (but stub with no slash works)
2) manual without .php conflicts with the apache manual :P
3) I can't seem to get it to work in subdirectories :-/

Anyway, Thanks for sharing this Isaac!

Jun 17, 2004 07:59

ah, just fixed my #1:

RewriteRule (^[^\./]+)/(.*)$ $1\.php/$2

Jun 17, 2004 08:05

ah, just found out how to get rid of the double rule!

I narrowed it down to this:

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/(news|manual)(.*)$
RewriteRule (^[^\./]+)(/.*)?$ $1\.php$2

Jun 17, 2004 08:52

Hehe that's me again getting high in one of those geeky reverse engineering moments :P

I just narrowed the 4 line thing down to one, and it works for subdorectories too!

Code

RewriteEngine On
RewriteRule ^(news|manual|dev/todo)(/.*)?$  $1\.php$2

news.php & manual.php are two stub files in the root.

todo.php is a stub file in the dev subdir.

One important thing to keep in mind is to set the stub/utl name to news and not news.php -- otherwise, b2evo won't recognize it and won't be able to decode the extrapath.

Jun 17, 2004 10:16

After reading the f*ing [url=http://httpd.apache.org/docs-2.0/mod/mod_rewrite.html]manual[/url]:

mod_rewrite maps the source suburl to a file, so it's not even necessary to pass the extrapath back, there is just no way to read it back from b2evo ltare (at least, none that I know of...)

So my single line can be further narrowed down to this:

Code

RewriteRule ^(news|manual|dev/todo)(/.*)?$  $1.php

(removed an unnecessary \ too)

How does it work?

1) check that the sub URL (relative to .htaccess) starts with news, manual or dev/todo AND that the only possible thing after that be an extra path (starting with /) (the querystring '?param=val' is not included in the suburl being tested here)

2) map this URL to a file using the same name we found at the start and ended with .php .

Jun 17, 2004 10:49

Hard to stop when you've started! :roll:

Here's the highest I could get:

Code

RewriteEngine On
RewriteCond %{REQUEST_FILENAME}.html  -s
RewriteCond %{QUERY_STRING}  ^$
RewriteRule ^(news|dev/todo)/?$  $1.html
RewriteRule ^(news|dev/todo)(/.*)?$  $1.php

Not only will this silently call the matching .php file for your stub, but before that it will check if you have generated a static .html page for the main page (when there are no parameters)

Jun 17, 2004 11:43

For those who did not realize by now, Isaac has turned me into a mod_rewrite junkie overnight!

Here's my latest fix:

Code

RewriteEngine On
 
# If we have an .html file for the bare subject (no extra path, no query string), use it:
RewriteCond %{REQUEST_FILENAME}.html  -s
RewriteCond %{QUERY_STRING}  ^$
RewriteRule ^(news|man|dev/todo)/?$  $1.html
 
# If the subject/extrapath does not match an existing file, call b2evo!
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(news|man|dev/todo)(/.*)?$  $1.php

This pushes the beauty of it all even further since it will allow you to have a folder with the same name as the stub, for example news, and it will allow you to fetch static files inside, for example /news/img/image.gif when /news is the static/dynamic main blog page, and /news/2004/06 the dynamic archive for june etc.

I just wonder if I can make this even better :P

Jun 17, 2004 18:15

Francois, that's nice!

I was using the same RewriteCond twice because you can't have one condition apply to multiple rules, even though you can have multiple conds apply to one rule. (The fix, of course, is to recode the conds and rules so that they apply to all cases, which is what you did.)

Mod_rewrite is really fun, but I haven't had time to really dig into it like I'd like to. (I also found out that it can mess up subdomains, if they're mapped to a folder. Had to put a separate .htaccess with "RewriteEngine Off" inside isaacschlueter.com/webreports to prevent the bad get errors when I went to webreports.isaacschlueter.com)

fp wrote:

I just wonder if I can make this even better

I wonder if you can, too. Here's the challenge, and I'll grant a prize to the first person who solves this :)

User requests http://example.com/foo/bar/1/2/3

It'll check these options, in order:
1. IF there's a file named foo.php (or foo.htm(l?), if there's no path info or query string), then go to foo.php/bar/1/2/3, or foo.htm(l?) - Quit here.
2. If no file named foo.php, then try a folder named /foo/, and start over in there.
3. If no folder named /foo/..., then rewrite to /index.php/foo/... - quit here.

If 2, then
1. Check for a file named bar.php (or bar.html? if there's nothing after that) - if it exists, rewrite to foo/bar.php/1/2/3 and stop
2. Else, check for a folder named foo/bar/ and start over in there if it exists.
3. Else, rewrite to foo/index.php/bar/1/2/3 and stop

etc.

User only gets a 404 error if it gets down to /foo/bar/1/2/3, and there is no 3.php, 3.htm, or 3.html, but any file or index.php in any of those directories along that road will stop the process.

Redeclaring the RewriteBase at each folder is acceptable, as is requiring that there be a separate .htaccess in each folder - but bonus points if you can do all that with a single file in the root. And, of course,

If you can do that and make it work without having error 500s for infinite rewrites loops, then you win the prize. I'm thinking it'll probably be something like $20, since i'm cheap, but if anyone else wants to contribute to the prize fund, you're more than welcome, of course! If you can do it in few enough lines, then the prize will be more.

I don't claim that this will be particularly useful, and it will probably have some wicked server overhead, but it's more for esthetic reasons that I want to see if it's possible, just because I think it'd be cool, so that's why I've been thinking about it, and why I'm offering a prize for solving the puzzle.

Jun 28, 2004 00:27

what i use is this

- name the stub file as "foobar" no .php
- add this to the .htaccess

Code

<Files ~ "(foobar)$">
  ForceType application/x-httpd-php
</Files>

if you have more than one stub file, use

Code

<Files ~ "(foobar|foobar1|foobar2)$">
  ForceType application/x-httpd-php
</Files>

Aug 05, 2004 13:29

What i use is this : (almost like kiesow)

<FilesMatch "^[^\.]*$">
ForceType application/x-httpd-php
</FilesMatch>

What?s the better way to get rid of the .php extension ?

[]?s
- Walter

Aug 05, 2004 17:41

Walter,
Read the other posts in this thread.

My files still have .php on them. But the .php is not in the *url*.

Aug 05, 2004 17:52

Oh ! .. i had renamed my php from files too..

Sorry me ! I will read the entire thread !

G?d bless yoU!

[]?s
- Walter

Aug 05, 2004 18:13

hey, Isaac, I have read everithing now... ;) Sorry me about the post before..

But I have another question.. I have other blogs hosted on my site..
I have 3 blogs on total :

http://waltercruz.com/blog/aprocura
http://waltercruz.com/blog/cancoes
http://waltercruz.com/blog/apaixonate

on the root of my site, I?m using a .htacess with these line:

Redirect /cancoes http://waltercruz.com/blog/cancoes
Redirect /aprocura http://waltercruz.com/blog/aprocura
Redirect /apaixonate http://waltercruz.com/blog/apaixonate

Yes ?

But this only redirects.. someone type http://waltercruz.com/aprocura to /blog/aprocura..

Can I alter the URL using the mod_rewrite ?

how this wil be ?

I think that will be someone like (in the root folder .htacess)

RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(aprocura|cancoes|apaixonate)(/.*)?$ /blog/$1.php

It?s right ?

thank you for all!

[]?s
- Walter

Aug 05, 2004 18:31

Yep, you've pretty much got it, walter.

Code

RewriteEngine On
 
# If we have an .html file for the bare subject (no extra path, no query string), use it:
RewriteCond %{REQUEST_FILENAME}.html  -s
RewriteCond %{QUERY_STRING}  ^$
RewriteRule ^(aprocura|cancoes|apaixonate)/?$  blog/$1.html
 
# If the subject/extrapath does not match an existing file, call b2evo!
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(aprocura|cancoes|apaixonate)(/.*)?$  blog/$1.php

B)

Aug 27, 2004 02:29

<bump> I have been playing with WordPress and they have some really nice rewrite templates to get some really meaningful and clean URIs out of the system.

So for example a value like:

/archives/%year%/%monthnum%/%day%/%postname%/

would give you a permalink like:

/archives/2003/05/23/my-cheese-sandwich/

It even generates the code to stick in the .htaccess file for your cut'n'paste delight.

It would be really nice to have this kind of functionality built into b2e, I am sure someone can sort this out - right?

Feb 20, 2005 15:36

Hello everybody!

Ok, so I have finally gotten clean urls to work, sort of. b2evo sits in a subdirectory called "blogs/"., and the page is correctly accessed when a url like this one is requested:
http://www.unsere-weltreise.net/blogs/devblog/2005/02/10/keuch_aetz_argh

As you can see, the page is loaded correctly, but the relative references from within that file do work anymore (stylesheets, etc.). Any idead how to fix that using .htaccess?

This is what I have in my .htaccess:

Code

RewriteEngine On
 
# If we have an .html file for the bare subject (no extra path, no query string), use it:
RewriteCond %{REQUEST_FILENAME}.html  -s
RewriteCond %{QUERY_STRING}  ^$
RewriteRule ^(krissi|ute|devblog)/?$  /blogs/$1.html
 
# If the subject/extrapath does not match an existing file, call b2evo!
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(krissi|ute|devblog)(/.*)?$  /blogs/$1.php

Thx a lot!

Feb 20, 2005 16:25

Ok, never mind, I fixed this using

Code

<base href="<?php echo ( $baseurl.'/' ); ?>"/>

which is ok, i guess. if there is a smarter way, using .htaccess, I'm all ears/eyes.

Thx.

May 01, 2005 15:11

Hello i was reading this post , and its very confusing , evry while a code is added or something is added ..

plz try 2 make it more readable .

my question is :

i added the following code in the .htacess

Code

RewriteEngine On
 
# If we have an .html file for the bare subject (no extra path, no query string), use it:
RewriteCond %{REQUEST_FILENAME}.html  -s
RewriteCond %{QUERY_STRING}  ^$
RewriteRule ^(new|ute|devblog)/?$  /blogs/$1.html
 
# If the subject/extrapath does not match an existing file, call b2evo!
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(new|ute|devblog)(/.*)?$  /blogs/$1.php

i have a b2evolution ,

www.domain.com/new

when i want to test if evrything is correct , i test something like

www.domain.com/new/2005/05

but i receive an error page

should i change something in the mode rewrite code ?

thank's

May 03, 2005 11:50

This is what I have on my site, and it works.

Code

RewriteEngine On
 
# If we have an .html file for the bare subject (no extra path, no query string), use it:
RewriteCond %{REQUEST_FILENAME}.html  -s
RewriteCond %{QUERY_STRING}  ^$
RewriteRule ^(all|blog|linkblog|click)/?$  $1.html
 
# If the subject/extrapath does not match an existing file, call b2evo!
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(all|blog|linkblog|click)(/.*)?$  $1.php

May 12, 2005 01:56

This rewrite setup works great and I'm using it on a site that just switched from Movable Type, but there's one problem. Each user has their own directory, user1, user2, etc. They each also have a stub file on the same level (web root) user1.php, user2.php. With my .htaccess set up like most of the people in this thread the users can keep static files in their folders, and use extra-path info, so www.brendoman.com/user1/photos/car.jpg goes to a static image file, but www.brendoman.com/user1/2005/05/car goes to a blog post. So, we can get files from their subfolders, but what we can't do is just go to one of the subfolders. Here's a real example: www.brendoman.com/wendytime/engagement/index.html works, but www.brendoman.com/wendytime/engagement just takes the browser back to wendytime.php . Is there a way to tweak the .htaccess file to make this work better?

May 20, 2005 22:58

Ok, PersonMan, correct me if I've got this wrong:

user1.php = blog stub for user "blah"
user1/... = user folder for "blah"

Requests for blah/whatever should go to the blog, IF it doesn't point at a file OR a folder.

So, if the folder structure is like this:

Code

root
  +-user1.php
  |
  +-user1
   |
   +-folder
    |
    +-index.html
    +-car.jpg
then a request for user1/folder/ should actually go to the FOLDER user1/folder, and NOT user1.php/folder.

If that's right, try this, replacing the "user1|user2|..." with the actual stub/folder names.

Code

RewriteEngine On
 
# If we have an .html file for the bare subject (no extra path, no query string), use it:
RewriteCond %{REQUEST_FILENAME}.html  -s
RewriteCond %{QUERY_STRING}  ^$
RewriteRule ^(user1|user2|user3)/?$  $1.html
 
# If the subject/extrapath does not match an existing file, call b2evo!
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(user1|user2|user3)(/.*)?$  $1.php
The !-d means "if the request filename does not resolve to a directory".

May 21, 2005 00:06

That did it. I added this line and it started working:

Code

RewriteCond %{REQUEST_FILENAME} !-d

Thanks, Isaac!

May 21, 2005 03:45

Oops. That won't work afterall. The problem comes when you type www.brendoman.com/wendytime in the address bar. The whole point of the mod_rewrite code is for that url to take you to the blog, but now it shows the directory contents. I could make a second stub file, call it index.php and put it in that folder.

May 23, 2005 20:33

How about this?

Code

RewriteEngine On
 
# If we have an .html file for the bare subject (no extra path, no query string), use it:
RewriteCond %{REQUEST_FILENAME}.html  -s
RewriteCond %{QUERY_STRING}  ^$
RewriteRule ^(user1|user2|user3)/?$  $1.html
 
# If the subject/extrapath does not match an existing file, call b2evo!
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(user1|user2|user3)(/.*)?$  $1.php
 
# since wendytime/ is a directory, it won't get the last rule,
# so do another one here.
RewriteCond %{REQUEST_FILENAME}.html !-s
RewriteRule ^(user1|user2|user3)$  $1.php

Jun 11, 2005 11:56

Hi,
This only seems to give me my default blog.
I have 3 blogs and whatever link i select it still stays on the default.

Code

RewriteEngine On
 
# If we have an .html file for the bare subject (no extra path, no query string), use it:
RewriteCond %{REQUEST_FILENAME}.html  -s
RewriteCond %{QUERY_STRING}  ^$
RewriteRule ^(all|religion|politics|links)/?$  $1.html
 
# If the subject/extrapath does not match an existing file, call b2evo!
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(all|religion|politics|links)(/.*)?$  $1.php

can anyone help?
thanks

Thanks I got it

Jul 23, 2006 12:20

Hi,

is it possible b2evolution changed the way to handle stub files? This is what I want:

domain/blog1
domain/blog2

but I can only get domain/blog1.php and domain/blog2.php

I tried the solutions posted for prior b2evolution versions, but I can't get them to work.

If I understand the prior postings right,

Code

RewriteCond %{REQUEST_URI} ^/(stub1|stub2|etc)(.*)$
RewriteRule (^[^\./]+)/(.+)$  $1\.php/$2

should stripp off .php extension. But it doesn't. I get an 404 error.

Using another option with automatically adding .php extension to names without extension shows the skin, but omittes the blog content that cannot be found.

May anybody help me? The URL of the page is http://www.amnesty-muenster-osnabrueck.de/ and, for example, http://www.amnesty-muenster-osnabrueck.de/1176.php.

Thanks,

Jan

PS.: mod rewrite is activated.

Jul 26, 2006 15:09

Hm, I really don't know what I'm doing wrong.

This is what my .htaccess looks like:

# Apache configuration for the blog folder

# this will select the default blog template to be displayed
# if the URL is just .../blogs/
<IfModule mod_dir.c>
DirectoryIndex index.php index.html
</IfModule>

# this will make register globals off in b2's directory
# just put a '#' sign before these three lines if you don't want that
<IfModule mod_php4.c>
php_flag register_globals off
</IfModule>

# If you're using Apache 2, you may wish to try this for clean URLs:
# AcceptPathInfo On

RewriteEngine On

# If we have an .html file for the bare subject (no extra path, no query string), use it:
RewriteCond %{REQUEST_FILENAME}.html -s
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^(1176|1178)/?$ $1.html

# If the subject/extrapath does not match an existing file, call b2evo!
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(1176|1178)(/.*)?$ $1.php

So, URL domain.com/1176 or /1176 should work, hm?

But they don't, as http://www.amnesty-muenster-osnabrueck.de/1176 and http://www.amnesty-muenster-osnabrueck.de/1178 show. :(

Would anybody be so kind to help me, please? I'm using 1.8-beta, and I really don't know what to do.

Thanks, Jan

Aug 01, 2006 17:37

Hm, anybody who has a clue?

In the meantime, I recognized the following .htaccess entry works basicly:

Code

RewriteEngine On
RewriteCond %{REQUEST_FILENAME}.html -s
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^(1176|1178)/?$ $1.html
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(1176|1178)(/.*)?$ http://www.amnesty-muenster-osnabrueck.de/$1.php

New is the addition http://www.amnesty-muenster-osnabrueck.de.

But there is one problem left: Visited URLs are not marked as visited links.

Maybe this is a first hint what the problem could be?[/code]

Aug 16, 2006 05:23

Is there a similar type mod for a Windows 2003 server? What's the "stub file" that's mentioned on the settings page?

Aug 16, 2006 10:25

This is a very old topic way back when b2evo was still version 0.8.x, started by somebody who is no longer in the b2evo team.

I'll close this one, cause it's no longer valid, and when somebody comes up with the right sollution for 1.8, that person can start a new topic


Form is loading...

multi-blog engine – This forum is powered by b2evolution CMS, a complete engine for your website.