我们看到一些网站,地址是以 .htm 或 .html 结尾的,形如 http://www.k810.com/html/guide/2/1.htm 这样的格式,其中有一部分是真的静态页面,有一些侧是伪静态的。
    静态和伪静态的网站我都有做过,其中伪静态的制作和维护都容易一些。所以先向大家介绍伪静态的实现方法。我这里介绍的方法并非用 URL Rewrite (URL重写)实现,不用改写复杂的 URL Rewrite 规则,制作维护起来更加简便。
    详细的案例请查看 http://www.k810.com/ 。由于像“会员中心”那些页面,需要登录才能访问的,就不做成伪静态了。否则容易暴露该站点的“静态页面”是假的,呵呵。
    第一步,Apache 配置。
    Apache 配置,要求在 httpd.conf 的 Directory-Options 中添加 MultiViews 支持。例如
<Directory "D:/wwwroot/">
    Options Indexes FollowSymLinks MultiViews
    ## 默认为 Options Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
    先介绍一下实现的原理。假如一个网页的动态地址为 guide.php?page=2&typeid=1 ,对应的伪静态地址为 html/guide/2/1.htm 。
    开启了 MultiViews 后,保证的根目录下没有 html/ 目录,然后新建 html.php 文件。访问地址 html/guide/2/1.htm 时,由于 Apache 找不到 html/ 目录,它会读取并用PHP解释 html.php 这个文件。所以我们要在 html.php 中,解读这个伪静态地址为对应的动态地址,然后向用户输出相应的内容。
    第二步,创建 html.php 文件。
    html.php 的代码及解释:
<? 
$parseformat = array(); // 变量格式设定: 
// 每个文件允许接受的 GET 变量,以 / 分隔 
// 静态地址中,每个值的顺序会与变量名顺序对应 
// 建议常用到的变量写在前面,可能不会接收到的变量写在后面 $parseformat['tech.php'] = 'page'; 
$parseformat['tech_type.php'] = 'typeid/page'; 
$parseformat['tech_details.php'] = 'id'; $parseformat['guide.php'] = 'page'; 
$parseformat['guide_details.php'] = 'id'; 
// SCRIPT_IN_ROOTPATH : 本文件相对 document_root 所在的文件夹(以 / 结尾) 
$this_script_path = str_replace('\\','/',dirname(__FILE__)."/"); 
if(!defined("SCRIPT_IN_ROOTPATH")){ 
    define("SCRIPT_IN_ROOTPATH", substr($this_script_path,strlen($_SERVER['DOCUMENT_ROOT']) ) ); 
} // 动态链接解释并规范化,返回一个动态链接对应的静态链接 
// 在链接向一个静态页面时需要调用,其中 $link 是一个动态链接的地址,如 xxx.php?typeid=1&page=2 
// 返回 html/xxx/1/2.htm 这样的格式 
function url($link){     global $parseformat;     //分解 $link 字符串为两部份,以 "?" 号分隔,前面部份是文件路径 $url_file,后面部份是请求字符串 $url_query 
    $url_file = $url_query = ''; 
    list($url_file,$url_query) = split('\?',$link,2); 
    //若是以 "/" 开头的绝对路径,则改为相对路径 
    if($url_file[0]=='/'){ 
        $url_file = substr($url_file,strlen(SCRIPT_IN_ROOTPATH)); 
    } 
    // 将文件路径 / 替换为 -- 
    $url_file = str_replace('/','--',$url_file); 
    //去掉文件名中的 ".php" 后缀 
    $file = substr($url_file,0,-4); 
    if(!$file) $file = "index"; 
    //将 url_query 的值解释到 $query_values 数组 
    $query_values = array(); 
    if($url_query) parse_str($url_query,$query_values); 
    // 该文件的变量格式,分解为数组 
    $format_arr = array(); 
    if($parseformat["$file.php"]) $format_arr = split('/',$parseformat["$file.php"]);     // 各个变量的值,按照变量名的出现顺序规范排列 
    $querys = array(); 
    foreach($format_arr as $fa){ 
        $querys[] = $query_values["$fa"]; 
    } 
    $query = join('/',$querys); 
    // 去除末尾 / 号 
    // 为什么会出现末尾的 / 号呢 
    // xxx.php?typeid=1&page=2 => html/xxx/1/2.htm 
    // xxx.php?typeid=1 => html/xxx/1/.htm 
    // 因为有些变量不一定要传值,但设置里面有这个变量,需要给它留一个位置 
    // 如果这个位置是在最后,就可以去掉了。 
    if(strrchr($query,'/')=='/'){ 
        $query = preg_replace('/\/+$/mis','',$query); 
    } 
    // 返回的链接,加上 .htm 字符。 
    // 看得出来 .htm 这几个字符其实是多余的,反向解释的时候还要先去掉呢 
    $htmlfile = SCRIPT_IN_ROOTPATH."html/".$file.($query?"/$query":"").".htm";     return $htmlfile; 

// 直接访问 html.php, 即用户访问的路径为伪静态地址时: 
// 这里是反向解释,把静态链接解释为对应的动态链接; 
// 把 html/xxx/1/2.htm 这样的访问格式,解释为 xxx.php?typeid=1&page=2 相同的效果 
if(basename($_SERVER['SCRIPT_FILENAME'])==basename(__FILE__)){     list($request_uri,) = split('\?',str_replace('\\','/',$_SERVER['REQUEST_URI']),2); // ?号后的去掉,HTML 的路径是不需要那部份的     // 访问路径,去掉 SCRIPT_IN_ROOTPATH 和 .htm 
    $uri_string = substr($request_uri,strlen(SCRIPT_IN_ROOTPATH),-4);     // 以 "/" 号为分隔,分解访问路径到数组中 
    // 第一项值当然是 html,第二项是没有后缀的实际文件路径,其他为各个请求变量对应的值。     $uri_string_arr = split('/',$uri_string);     //文件路径,加回 .php 后缀 
    $phpfile = str_replace('--','/',$uri_string_arr[1]).".php";     // $_SERVER['PHP_SELF'] 这个系统变量, 用伪静态访问的话,会是 html.php ... 
    $_SERVER['PHP_SELF'] = SCRIPT_IN_ROOTPATH.$phpfile;     //读取变量的格式,分解为数组 
    $format_arr = array(); 
    if($parseformat["$phpfile"]) $format_arr = split('/',$parseformat["$phpfile"]);     //静态地址中的变量值,把它们赋值到 $_REQUEST 和 $_GET 对应的变量中:     for($i=0;$i<count($format_arr);$i++){ 
        if(isset($uri_string_arr[$i+2]) && $format_arr[$i]){ 
            $queryvalue = urldecode($uri_string_arr[$i+2]); 
            if(!isset($_REQUEST["$format_arr[$i]"])) $_REQUEST["$format_arr[$i]"] = $queryvalue; 
            if(!isset($_GET["$format_arr[$i]"])) $_GET["$format_arr[$i]"] = $queryvalue; 
        } 
    }     //include 实际的文件 
    chdir(dirname($phpfile)) && @include($this_script_path.$phpfile); } 
?> 
    第三步,包含 html.php 。
    其他页面,包括指向 guide.php 的页面和 guide.php 页面本身,只需要以 <? include_once("html.php");?> 开头,再添加其他内容即可。    第四步,添加 BASE HREF 。
    由于伪静态页面的路径和动态的不一样,导致浏览器解释到的目录不同,所以需要在 HTML 代码的<HEAD>部分,添加 BASE HREF 标签,代码如
<base href='http://www.k810.com/' />
其中的网址改为你自己的网站地址。
    第五步,链接改写。
    其中指向伪静态页面的链接,写为类似<?=url("guide.php?page=2&typeid=1");?> 这样的格式,得到标准的伪静态链接。例如
<? include_once("html.php");?> 
<html> 
  <head> 
    <title>快精灵</title> 
    <base href='http://www.k810.com/' /> 
  <head> 
  <body> 
    <a href="./">首页</a> 
    <a href="<?=url("guide.php?page=2&typeid=1");?>">设计指南</a> 
  </body> 
</html> 
    至此,我们的伪静态页面制作完成。添加多个伪静态页面,只要改下程序,并不需要再改写 URL Rewrite 规则,或者虚拟机上多个站点需要制作成伪静态页面,这种方式显得特别简单。
    要改回动态的站点,只需要把 html.php 的内容改为 <? function url($link){return $link;} ?>  即可,是不是很方便呢?
    我制作了简单的实例供参考,需要的朋友可以点击如下地址下载:http://www.k810.com/html/article/83.htm