是否可以反向映射mod_rewrite URL?

时间:2009-06-30 08:42:24

标签: url-rewriting

我使用.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文件是保存此数据的唯一位置......

3 个答案:

答案 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)

您可以通过两种方式实现这一目标:

  1. via .htaccess
  2. 通过phpcode
  3. 无论哪种方式,请务必不要陷入重定向循环。

    通过.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;
    }
}