2009-06-30 64 views
0

我有一個簡單的URL重寫設置與.htaccess文件。摘錄:是否可以映射mod_rewrite URL的反向?

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

如果任何人有興趣,我自己用這個(可能是絕對可怕的)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; 
    } 
} 
0

您可以通過兩種方式來完成它:

  1. 通過的.htaccess
  2. 通過phpcode

在這兩種方式,一定不要陷入重定向循環。

通過的.htaccess

使用的RewriteCond檢查QUERY_STRING和redirect depending on the querystring。不要忘記添加[L]標誌以防止Apache繼續執行其他重寫規則和R = 301標誌來重定向客戶端。

通過PHP

在這裏,你必須從客戶端的請求,並請求與服務器之間進行區分。你可能想改變你的重寫規則,並通過一個額外的參數,例如

RewriteRule ^home(/)?$ index.php?mod=frontpage&com=showFrontpage&server=1 

然後,在你的代碼,檢查參數是否存在,如果不重定向。

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