Search code examples
apache.htaccessmod-rewrite

Convert Query Parameters to Pretty URL


I have script file post.php which I'm using without .php extension using code below

Options -Indexes

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [NC,L]

I want to use a pretty URL. For example, when I request the URL /post/12 it should give me $_GET parameter 12 like I'm using with a query string: post?id=12.

Is it possible? Also, I don't want to direct all requests to index.php. Only requests that are made to posts.php script.


Solution

  • Handle requests of the form /post/12 with a separate rule, before your generic rewrite that appends the .php extension.

    Try it like this:

    Options -Indexes -MultiViews
    
    RewriteEngine On
    
    # Remove trailing slash if not a directory
    # eg. "/post/" is redirected to "/post"
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule (.*)/$ /$1 [R=301,L]
    
    # Rewrite "/post/<id>" to "/post.php?id=<id>"
    RewriteRule ^(post)/(\d+)$ $1.php?id=$2 [L]
    
    # Rewrite "/post" to "/post.php" (and other extensionless URLs)
    RewriteCond %{DOCUMENT_ROOT}/$1.php -f
    RewriteRule (.*) $1.php [L]
    

    Notes:

    • MultiViews needs to be disabled for the second rule to work.
    • Your initial rule that appends the .php extension was not quite correct. It could have resulted in a 500 error under certain conditions. However, the first condition was superfluous - there's no point checking that the request does not map to a file before checking that the request + .php does map to a file. These are mutually inclusive expressions.
    • Without the first rule that removes the trailing slash (eg. /post/ to /post) it raises the question of what to do with a request for /post/ (without an id) - should this serve /post.php (the same as /post) or /post.php?id= (empty URl param)? Both of which are presumably the same thing anyway. However, these would both result in duplicate content (potentially), hence the need for a redirect.