A frequent question about URL rewriting goes something like this:
I currently have URLs that look like this:
I made them pretty like this:
By using this in my .htaccess file:
RewriteRule my-blog/(\d+)--i-found-the-answer my-blog/entry.php?id=$1
But I want them to look like this:
How can I change my .htaccess file to make that work?
The simple answer is that you can't.
Rewrite rules don't make ugly URLs pretty, they make pretty URLs ugly
Whenever you type in a URL in a web browser, or follow a link, or display a page that references an image, etc, the browser makes a request for a particular URL. That request ends up at a web server, and the web server gives a response.
A rewrite rule is simply a rule that says "when the browser requests a URL that looks like X, give them the same response as if they'd requested Y".
When we make rules to handle "pretty URLs", the request is the pretty URL, and the response is based on the internal ugly URL. It can't go the other way around, because we're writing the rule on the server, and all the server sees is the request the browser sent it.
You can't use information that you don't have
Given this basic model of what a rewrite rule does, imagine you were giving the instructions to a human. You could say:
- If you see a number in the request, like the "42" in "http://example.com/my-blog/42--i-found-the-answer", put that number on the end of "my-blog/entry.php?id="
But if the information isn't there in the request, your instructions won't make any sense:
- If the request has "my-blog" in it, like "http://example.com/my-blog/i-found-the-answer", put the right number on the end of "my-blog/entry.php?id="
The person reading those instructions is going to say "Sorry, how do I know what the right number is?"
Redirects: "This URL is currently out of office..."
Sometimes, you see rules that are the other way around, like this:
RewriteRule my-blog/entry.php?id=(\d+) my-blog/$1--i-found-the-answer [R]
This rule does match an ugly URL on the left, and produce a pretty URL on the right. So surely we could write it without the ID at the beginning of the pretty part?
RewriteRule my-blog/entry.php?id=(\d+) my-blog/i-found-the-answer [R]
The important difference is the [R]
flag, which means that this rule is actually a redirect - instead of "serve the response from this URL", it means "tell the browser to load this URL instead".
You can think of this like one of those automated e-mail replies, saying "Sorry, Joe Bloggs is currently on holiday; please send your message to Jane Smith instead." In the same way, the redirect above tells the browser "Sorry, there's no content for http://example.com/my-blog/entry.php?id=42
; please request http://example.com/my-blog/42--i-found-the-answer
instead.
The important point of this analogy is that the above message wouldn't be much use if there wasn't actually anyone called Jane Smith working there, or if they had no idea how to answer the questions Joe Bloggs normally dealt with. Similarly, a redirect is no use if the URL you tell the browser to request doesn't actually do anything useful. Once the browser follows the redirect, it's going to make a new request, and when the server receives the new request, it still won't know what the ID number is.
But some sites do it, so it must be possible!
A web server only has the information present in the request, but how it uses that information is up to you.
For instance, rather than looking up a blog post by ID, you could store its URL directly in the database, then write some code to do the matching directly in PHP, Python, node.js, etc. Or you could have the same URL show different content based on the language the user has set in their browser, or based on a cookie, etc.
Another thing you can do is use a form (or API request) with a method of POST rather than GET. That means additional information is sent in the "body" of the request, separate from the URL. It still has to be sent, but it's not as obvious in the browser, won't be included in bookmarks, etc.
But you can't write a single line in a .htaccess file that performs miracles.