I am trying to use apache-rewrite rule to convert the below URL:
http://localhost/foo/bar/news.php?id=24
Into this
Can you see if this works?
RewriteEngine On
RewriteBase /DIRECTORY/AID/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
^news/([A-Za-z0-9_]+)$ news.php?id=$1 [QSA,L]
EDIT : Fixed the regex character class definitions.
If you feel your .htaccess
file is not working as intended then this is a server configuration issue and most likely to do with the AllowOverride
directive under the Apache configuration.
In your http.conf
file find the section which looks something as follows:
<Directory>
Options FollowSymLinks
AllowOverride None
</Directory>
Change the AllowOverride
directive to allow All
.
<Directory>
Options FollowSymLinks
AllowOverride All
</Directory>
The next thing is to ensure that the mod_rewrite
module is enabled for your XAMPP install. Search for the following line:
#LoadModule rewrite_module modules/mod_rewrite.so
Remove the #
so it looks like so:
LoadModule rewrite_module modules/mod_rewrite.so
Restart the Apache service after saving all your changes.
Also ensure you are using the RewriteBase
directive in your .htaccess
configuration as follows:
RewriteEngine On
RewriteBase /DIRECTORY/AID/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
^news/([A-Za-z0-9_]+)(/)?$ news.php?title=$1 [QSA,L]
The next thing is to ensure your links are pointing to the Rewrite URL. Your echo line should be something like the following:
echo "<a href=\"news/" . $row['title'] . "\"> " . substr($row['title'], 0, 26) . "...</a><br />";
Now since you can only retrieve titles with this URL rewrite method we need to configure your PHP script accordingly to retrieve the content based on the title. If you still want to use "id" only for retrieving the record then your Rewrite URL should contain the "id" in it in some form. Typical examples of this form are:
news/the_news_title_123
news/123_the_news_title
news/123/the_news_title
You are missing the title of the URL. If you wish to show that in URL, then you must include it in the link as well, like this:
<a href="news.php?news_id=$id&title=$url_tile">
This seems to be a complicated problem because you do not know where it really is doing wrong.
I would suggest you divide what you want to do into small parts and make each of them work properly before you join them together. For example:
1. Make sure .htaccess file is readable and can do some simple thing, preventing directory indexing for instance.
2. Make sure you can redirect something with simple html code.
3. Make sure you can run Felipe's example code successfully. From here you can get good picture of what is going on.
And as a side note:
It is more common to rewrite like this:
http://localhost/DIRECTORY/AID/news.php?a_id=24 TO -->
http://localhost/DIRECTORY/AID/news/24_this_is_article_title
Notice the id 24 is still carried over to the rewritten url. That will make pattern matching simpler and avoid unnecessary processing of title duplication.
First of all, you would need to change the href in the html, to give the new url format
function news_preview() {
$query = "SELECT * FROM news ORDER BY id DESC LIMIT 5 ";
$result = mysql_query($query) or die(mysql_error());
while($row=mysql_fetch_array($result))
{
echo "<a href=\"/news/$row[id]\"> ". substr($row['title'], 0,26)."...</a><br/>".; }
}
The will generate urls like http://localhost/news/24
Note that I removed the /DIRECTORY/AID
from the url, as the htaccess suggest you want that to be url, as opposed to what you stated in the text.
But now the get to the http://localhost/news/this_is_article_title
type of url. Because there is no correlation between this_is_article_title
and the id 24
, the only way to achieve this is by either adding the id to the url too, or to have the php lookup the news-article with this title in the database.
This last solution however has some problems, as the you can't just us the title in a url. You have to escape characters. Also you'll have to add a index for the title row in the DB for better performance.
So I'll go with the first solution. We will generate urls like this
http://localhost/news/24/this_is_article_title
First the php part
function news_preview() {
$query = "SELECT * FROM news ORDER BY id DESC LIMIT 5 ";
$result = mysql_query($query) or die(mysql_error());
while($row=mysql_fetch_array($result))
{
$url = "/news/$row[id]/".preg_replace('/[^a-zA-Z0-9-_]/', '_', $row['title']);
echo "<a href=\"$url\"> ". substr($row['title'], 0,26)."...</a><br/>".; }
}
Next comes the htaccess part.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^news/([0-9]+)/([A-Za-z0-9_-]+)$ DIRECTORY/AID/news.php?id=$1 [QSA,L]
That should do it I think.
Change the link:
echo "<a href=\"news.php?news=$row[id]\"> ". substr($row['title'], 0,26)."</a>
to
echo "<a href=\"news/$row['title']\">".$row['title']."</a>"
That way, the link will go to news/$row['title']
instead of news.php?id=...
. And now in the page DIRECOTORY/AID/news.php
, you should get the id
and check if it is a number OR text, and in case of text match it up with the $row['title']
and then load the page accordingly.
Notes:
If the title is not going to be unique then you should probably do news/{id}/{title}
and then in rewrite it to DIRECTORY/AID/news.php?id={id}&title={title}
and then you can base it off of the ID instead of the title.
Hope that helps.