Apache URL重写不正常

时间:2012-11-26 02:00:55

标签: php apache .htaccess url-rewriting

我正在尝试使用apache-rewrite规则转换以下网址:

  

http://localhost/foo/bar/news.php?id=24

采用以下格式:

  

http://localhost/foo/bar/news/foo-bar

数字24是MySQL表中随机行的id,其中还包含titlecontent个字段。

MariaDB [blog]> select * from articles;
+----+---------+----------+ 
| id | title   | content  |
+----+---------+----------+ 
|  1 | foo-bar | bla bla  | 
+----+---------+----------+ 
1 row in set (0.00 sec)

我的.htaccess内有以下规则:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
^news/([A_Za_z0_9_]+)$ DIRECTORY/AID/news.php?id=$1 [QSA,L]

我还有一个PHP代码,可以生成如下链接:

$link = "<a href='news.php?id={$row['id']}'></a>";
echo $link;  

但是,我无法获得重写规则来将路径更改为所需的最终结果。

12 个答案:

答案 0 :(得分:4)

替换(真实)URL有一个数字-Code-来标识链接(根据您的描述): http://localhost/DIRECTORY/AID/news.php?news = 42 < / EM>

在这种情况下,该代码 42 ,但您想要显示的网址没有。没有这个数字,我们总会得到错误404。这只是输入: http://localhost/DIRECTORY/AID/news.php?news =

例如,必须通过在“/”之后添加代码来修改您想要显示的URL。可以是连字符等,但必须相应地修改正则表达式。

以下示例输入: http:// localhost / news / 42 / 转到 http:// localhost / DIRECTORY / AID / news.php新闻= 42

RewriteEngine On
RewriteRule ^news/([0-9]+)/?$ DIRECTORY/AID/news.php?news=$1 [NC,L]

这就是你所需要的一切。要测试此示例,请在 http:// localhost / DIRECTORY / AID /

中的 news.php 中插入此代码。
<?php
if ( $_GET[ 'news' ] == '42' ) {
  echo  "HERE I AM<br /><br />";
}
?>

根据OP描述更新。可以使用任何名称代替 This_is_news

RewriteEngine On
RewriteRule ^news/([0-9a-zA-Z-_]+)/?$ DIRECTORY/AID/news.php?news=$1 [NC,L]

答案 1 :(得分:2)

首先,您需要更改html中的href,以提供新的url格式

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/>".; }
}

会生成http://localhost/news/24

等网址

请注意,我从网址中删除了/DIRECTORY/AID,因为htaccess建议您将其设为网址,而不是您在文中所说的内容。

但现在转到http://localhost/news/this_is_article_title类型的网址。因为this_is_article_title和id 24之间没有相关性,所以实现这一点的唯一方法是将id添加到url中,或者让php查找带有此标题的新闻文章在数据库中。

然而,这最后一个解决方案存在一些问题,因为你不能只是我们在网址中的标题。你必须逃避角色。此外,您还必须为数据库中的标题行添加索引以获得更好的性能。

所以我会选择第一个解决方案。我们将生成这样的网址

http://localhost/news/24/this_is_article_title

首先是php部分

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/>".; }
}

接下来是htaccess部分。

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]

我认为应该这样做。

答案 2 :(得分:1)

在RewriteEngine On后立即放置RewriteBase 在开始重定向之前,它会正确设置重写引擎

答案 3 :(得分:1)

不幸的是我无法在PHP或Apache中回答您的问题(虽然我使用手动REST转换器在我当前项目中创建URL地址),但据我所知,您希望用户输入 http://localhost/DIRECTORY/AID/article.php?a_id = 24 ,地址栏最终应该像 http:// localhost / DIRECTORY / AID / news / this_is_article_title

我不完全确定这为您提供了哪些好处,请注意我的解决方案不允许您的最终用户键入RESTful URL并最终到达带有QueryString地址的页面。你需要一些额外的工作才能做到这一点,甚至需要更多的工作来使它与数据库保持同步(我建议使用一个脚本来取消RESTFUL URL,查询数据库中的主题然后返回ID或页面内容。 ..但这是另一天不同的Stack Overflow问题。

<强>解 我提出的解决方案需要HTML5 doctype和非常轻松的Javascript。

history.replaceState(null, "history title here", "news/this_is_article_title");

这样做是在不触发页面重定向,重新加载或其他任何内容的情况下更改地址栏中的URL。这个javascript可以用PHP动态编写,以便在提供页面时更新地址。文档越高,变化越快。

这是一个jsFiddle链接:http://jsfiddle.net/uT3RP/1/

不幸的是,他们在iframe中运行代码,因此它无法控制主地址栏,因此我提供了一个警告,显示地址栏位置所说的内容,以便进行校对。这不是最优雅的解决方案。如果没有确保显示的URL可以用于访问同一页面的故障,我甚至不建议你做你正在做的事情。免责声明...你的问题通过1行js和doctype更改解决(如果你没有使用HTML5)。

你可以停止鞭打贫穷的'htaccess并继续你的项目:)

答案 4 :(得分:1)

这是关于URL重写和字符串到ID算法的问题。

最重要的是,请记住,您的网址通过重写模块更改,浏览器栏中的网址始终包含像id或字符串一样的帖子参数(关于您的新闻)。

现在回答这个问题。我们的目的只是重写网址:

http://localhost/DIRECTORY/AID/news/this_is_article_title

为:

http://localhost/DIRECTORY/AID/news.php?a_id=24

使用重写模块,我们只能将其重写为:

http://localhost/DIRECTORY/AID/news.php?title=this_is_article_title

这是htaccess部分,alrealdy在htaccess-online-tester

上测试
RewriteRule ^DIRECTORY/AID/news/([A-Za-z0-9_]+)$ DIRECTORY/AID/news.php?title=$1 [QSA,L]

剩下的工作是构建一个算法,用于将标题映射到新闻,重写模块无法帮助我们(特别是你手动重写url)。我们可以使用下面的PHP代码:

<?php

//write url reflect to news title.
function build_news_url_by_title(){
    $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/".strtr(substr($row['title'], 0,26), " ", "_")."\">".substr($row['title'], 0,26)."</a>";
    }   
}

function get_news_by_title($title){
    $real_title = strtr($title, "_", " ");
    $query = "SELECT * FROM news WHERE title LIKE %".$real_title."% LIMIT 1";
    return mysql_query($query) or die(mysql_error());
}

$title = $_POST['title'];

$news = get_news_by_title($title);

//some code return the news
...

所以网址:

http://localhost/DIRECTORY/AID/news/this_is_article_title

也可以给我们这个消息。

最后,根据上述步骤,如果我们输入网址

http://localhost/DIRECTORY/AID/news/this_is_article_title

在浏览器栏中,它也可以给我们提供新闻。它没有关于愚蠢ID的商务。虽然上面的代码可能存在一些错误,但不要将它放在产品服务器上。

答案 5 :(得分:1)

你能看出这是否有效吗?

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]

编辑:修正了正则表达式字符类定义。

答案 6 :(得分:1)

您缺少网址标题。如果您希望在URL中显示该内容,则必须将其包含在链接中,如下所示:

<a href="news.php?news_id=$id&title=$url_tile">

答案 7 :(得分:1)

这似乎是一个复杂的问题,因为你不知道它在哪里做错了。

我建议你把你想做的事情分成小部分,然后在你把它们连在一起之前让它们正常工作。例如:

 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. 

作为旁注:

更常见的是这样重写:

http://localhost/DIRECTORY/AID/news.php?a_id=24 TO -->
http://localhost/DIRECTORY/AID/news/24_this_is_article_title 

请注意,ID 24仍然被转移到重写的URL。这将使模式匹配更简单,避免不必要的标题重复处理。

答案 8 :(得分:1)

更改链接:

echo "<a href=\"news.php?news=$row[id]\"> ". substr($row['title'], 0,26)."</a>

echo "<a href=\"news/$row['title']\">".$row['title']."</a>"

这样,该链接将转到news/$row['title'],而不是news.php?id=...。现在,在页面DIRECOTORY/AID/news.php中,您应该获取id并检查它是否为数字 OR 文本,如果文本与{{1}相匹配然后相应地加载页面。

注意:

  1. 这假设$ row ['title']在所有其他行中是唯一的。
  2. 标题不包含非HTML内容,在这种情况下,您必须使用URL转义这些字符。
  3. 如果标题不是唯一的,那么您应该$row['title']然后将其重写为news/{id}/{title},然后您可以将其基于ID而不是标题。

    希望有所帮助。

答案 9 :(得分:1)

如果您认为.htaccess文件未按预期工作,则这是服务器配置问题,并且很可能与Apache配置下的AllowOverride指令有关。

http.conf文件中,找到如下所示的部分:

<Directory>
    Options FollowSymLinks
    AllowOverride None
</Directory>

AllowOverride指令更改为允许All

<Directory>
    Options FollowSymLinks
    AllowOverride All
</Directory>

接下来要确保为您的XAMPP安装启用mod_rewrite模块。搜索以下行:

#LoadModule rewrite_module modules/mod_rewrite.so

删除#,使其如下所示:

LoadModule rewrite_module modules/mod_rewrite.so
保存所有更改后,

重新启动Apache服务

同时确保您在RewriteBase配置中使用.htaccess指令,如下所示:

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]

接下来要确保您的链接指向重写URL。您的回声线应如下所示:

echo "<a href=\"news/" . $row['title'] . "\">  " . substr($row['title'], 0, 26) . "...</a><br />";

现在,由于您只能使用此URL重写方法检索标题,因此我们需要相应地配置您的PHP脚本以根据标题检索内容。如果您仍然只想使用“id”来检索记录,那么您的重写URL应该以某种形式包含“id”。这种形式的典型例子是:

  • news/the_news_title_123
  • news/123_the_news_title
  • news/123/the_news_title

答案 10 :(得分:0)

我无法评论,所以我必须回答。

阅读所有答案和您的问题,目前尚不清楚您想要什么。至少对于我来说。你说,例如:

http://localhost/DIRECTORY/AID/article.php?a_id=24

http://localhost/DIRECTORY/AID/article/this_is_article_title

但我想这不太对,除非你想要

http://localhost/DIRECTORY/AID/article.php?a_id=24

是在浏览器地址栏中输入的URL,如果是,那么重定向的目的是什么?最后,任何访问者都必须准确输入您不希望他们输入的内容。

我的猜测是你要输入友好的URL:

http://localhost/DIRECTORY/AID/article/this_is_article_title,所以问题应该是相反的方式:

http://localhost/DIRECTORY/AID/article/this_is_article_title TO

http://localhost/DIRECTORY/AID/article.php?a_id=24

接下来似乎并不清楚的是浏览器栏中显示的内容?唯一的答案是:输入的URL。它无法表现出任何不同的东西。

简而言之:如果您想在地址栏中显示 http:// localhost / DIRECTORY / AID / article / this_is_article_title ,那就是您必须输入的内容。真正的URL,SUBSTITUTION( http://localhost/DIRECTORY/AID/article.php?a_id = 24 )永远不会显示,也永远不会输入。这就是重定向的用途。

另一方面,目前尚不清楚news.php提供的ID号如何转换为 article / this_is_article_title 等字符串。 ¿这些字符串在哪里,有多少ID号,应该使用什么样的算法或公式来实现转换,哪些ID是你在评论中提到的'root',如何识别它们等等?你应该详细说明这一点,因为它似乎是你以前的评论的即兴和不连贯。

当然,我可能错了。我只是想猜测你的问题。

请天才,不要低估这个答案,请阅读。我不是想回答这个问题而且我真的不是一个天才。

答案 11 :(得分:-2)

看起来你已经忘记了“news.php”前面的斜线。