我使用.htaccess
文件进行简单的网址重写设置。摘录:
RewriteEngine On
RewriteRule ^home(/)?$ index.php?mod=frontpage&com=showFrontpage
RewriteRule ^signup(/)?$ index.php?mod=usermanager&com=showRegistrationForm
这完全没问题。但是,对旧样式URL的请求也是如此。当这样的请求进来时,我想执行301永久重定向到SEO友好URL,但我似乎无法弄清楚如何将/index.php?mod=frontpage&com=showFrontpage
映射到/home
。我是否必须解析.htaccess文件并对此进行一些正则表达式攻击?
URL重写是在项目推出后很晚才引入的,因此PHP脚本不会“意识到”正在进行的URL重写; .htaccess
文件是保存此数据的唯一位置......
答案 0 :(得分:1)
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/index.php$
RewriteCond %{QUERY_STRING} ^id=(.*)$
RewriteRule ^(.*)$ /home/%1? [R=302]
example.com/index.php?id=uri 将重定向到: example.com/home/uri
答案 1 :(得分:0)
您可以通过两种方式实现这一目标:
无论哪种方式,请务必不要陷入重定向循环。
通过.htaccess
使用RewriteCond检查QUERY_STRING和redirect depending on the querystring。不要忘记添加[L]标志以防止Apache继续执行其他重写规则,并且R = 301标志以重定向客户端。
通过php
在这里,您必须区分来自客户端的请求和来自服务器的请求。您可能希望更改重写规则并传递其他参数,例如
RewriteRule ^home(/)?$ index.php?mod=frontpage&com=showFrontpage&server=1
然后,在您的代码中,检查参数是否存在,否则重定向。
答案 2 :(得分:0)
如果有人感兴趣,我自己用这个(可能绝对可怕的)PHP代码解决了这个问题。
class clsURL {
static function checkURL() {
// don't allow requests on old style URL's
if (($_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING']) == $_SERVER['REQUEST_URI'] &&
$_SERVER['REQUEST_METHOD'] != 'POST') {
// redirect to new style URL
$redirectTable = self::createReverseTable();
$currentURL = $_SERVER['REQUEST_URI'];
if (substr($currentURL, 0, 1) == "/")
$currentURL = substr($currentURL, 1);
$newURL = self::getReverseURL($currentURL, $redirectTable);
if ($newURL) {
header ('HTTP/1.1 301 Moved Permanently');
header ('Location: /' . $newURL);
exit;
}
}
}
static function getReverseURL($current, $reverseTable) {
// filter out some common stuff
$current = preg_replace("/&mid=[0-9]+/", "", $current);
foreach ($reverseTable as $pair) {
if (preg_match("|" . $pair['from'] . "|", $current)) {
return preg_replace("|" . $pair['from'] . "|", $pair['to'], $current);
}
}
// nothing found
return false;
}
static function createReverseTable() {
$file = fopen('.htaccess', 'r');
$reverse = array();
while ($line = fgets($file)) {
if (stripos($line, 'RewriteRule') === 0) {
$parts = preg_split("/[\\s\\t]/", $line, 3, PREG_SPLIT_NO_EMPTY);
$regex = trim($parts[1]);
$url = trim($parts[2]);
$parts[2] = $url;
$matches = array();
if (preg_match_all("/\\$[0-9]/", $url, $matches)) {
$matches = $matches[0]; // why? don't know.
$from = str_replace('?', '\\?', $url);
$to = $regex;
foreach ($matches as $match) {
$index = substr($match, 1);
$bracket = 0;
for ($i = 0; $i < strlen($regex); ++$i) {
if (substr($regex, $i, 1) == "(") {
$bracket++;
if ($bracket == $index) {
$pattern = "";
$j = $i + 1;
while (substr($regex, $j, 1) != ")") {
$pattern .= substr($regex, $j, 1);
$j++;
}
$from = str_replace('$' . $index, '(' . $pattern . ')', $from);
$to = preg_replace('/\\(' . preg_quote($pattern, '/') . '\\)/', '\\$' . $index, $to, 1);
}
}
}
}
// remove optional stuff that we don't use
$to = str_replace('(-(.*))?', '', $to);
// remove ^ and (/)?$
$to = substr($to, 1);
if (substr($to, -5) == '(/)?$')
$to = substr($to, 0, strlen($to) - 5);
$from = '^' . $from . '$';
// index.php is optional
$from = str_replace('index.php', '(?:index\\.php)?', $from);
$reverse[] = array(
'from' => $from,
'to' => $to
);
} else {
$from = str_replace('?', '\\?', $url);
$to = $regex;
// remove ^ and (/)?$
$to = substr($to, 1);
if (substr($to, -5) == '(/)?$')
$to = substr($to, 0, strlen($to) - 5);
$from = '^' . $from . '$';
// index.php is optional
$from = str_replace('index.php', '(?:index\\.php)?', $from);
$reverse[] = array(
'from' => $from,
'to' => $to
);
}
}
}
fclose($file);
return $reverse;
}
}