使用htaccess和modrewrite缓存整个PHP输出到静态HTML


caching whole php output to static html using htaccess and modrewrite

我有一个Php网站,它已经为一些页面创建了一个完整的输出缓存文件,虽然没有保存为.html,并且在请求上仍然从Php发送,它错过了静态文件的托管缓存,具有非常好的性能。

缓存文件根据其md5(Url)保存在一个目录中。

我想知道是否与mod_rewrite将有可能获得类似的结果,但与html静态文件,我想我已经看到了类似的东西前一段时间与WordPress缓存插件(但在当时我没有太注意)。

我可以用什么代替md5()mod_rewrite转换整个Url在一个有效的唯一的文件名?

我的Url是虚拟路由,非常简单:/level1/level2/level3/(是一个仍在进行中的工作,但我不认为使用超过3个级别,levelN显然是一个例子,可以是任何单词)

我想简化一下:

mod_rewrite:/cache/unique(Url).html exist?加载它

php:/cache/unique(Url).html不存在?

创建它

我可以为unique使用什么?

是的,你可以这样做,我不打算提供整个代码,只是想法就足够了。

.htaccess
开始编写.htaccess的方式是将每个丢失的文件重定向到目录索引。它可以是这样的

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]

现在你将得到请求到index.php如果被调用的页面是没有找到。

与其使用散列文件名,不如使用目录结构,这样会更快,更容易读懂。

您可以动态地创建目录。

在<<p> strong> index . php
在将数据推回浏览器之前,请确保所有数据都保存在一个变量中。您可以使用include函数来做到这一点。参见本页例5。

根据目录级别保存数据。

$levels = explode('/',<REQUESTED_URI>);
$filename = array_pop($levels);
foreach($levels as $level)
   // Create Directory if does not exit

最后,这只是基本的想法,你必须自己找出技巧和技巧。

最后很简单,虽然我必须使用相同的目录和Url的子目录,但我记得的WordPress插件是超级缓存,我使用的mod_rewrite几乎是相同的。

使用.htaccessmod_rewrite转换Url是可能的,但并不简单,并且有一些限制(但即使是md5使用RewriteMapprg,如果您有权访问服务器配置)。

.htaccess如果静态缓存文件存在,加载它:

RewriteCond %{DOCUMENT_ROOT}/cache/$1/index.html -f
RewriteRule ^(.*) /cache/$1/index.html [L]

Php,我使用CodeIgniter,但应该很容易编辑Php,也许使用ob_startob_get_clean:

private function cache_output() {
    $this->load->helper('url');
    $uri = uri_string(); /* expect something like: level1/level2 (no heading/trailing slash */ 
    $dir = FCPATH.'cache'.DIRECTORY_SEPARATOR.str_replace('/',DIRECTORY_SEPARATOR,$uri);
    $file = $dir.DIRECTORY_SEPARATOR.'index.html';
    if (!file_exists($file)) {
        if (!is_dir($dir)) {
            mkdir($dir, 0755 & ~umask(), TRUE);
        }
        $output = $this->output->get_output();
        file_put_contents($file, $output);
        chmod($file, 0644 & ~umask());
    }
}

我几年前使用过类似的东西,并设法找到了源代码。我的.htaccess设置看起来像这样:

Options +FollowSymlinks
RewriteEngine on
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{DOCUMENT_ROOT}/cache/index.html -f
RewriteRule ^$ /cache/index.html [QSA,L]
RewriteCond %{REQUEST_METHOD} !POST
RewriteCond %{DOCUMENT_ROOT}/cache/$1.html -f
RewriteRule ^(.*[^/])/?$ /cache/$1.html [L]
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)?$ ./index.php [L]

它支持通过不同的文件名获取起始页,并且在任何post请求时跳过缓存。

生成该文件的PHP代码非常简单:
ob_start();
// ... main page code & output
$url = $_SERVER['REQUEST_URI'];
$html = ob_get_clean();
$start = array('/', '', '/index.php');
$blacklisted = array('/some/url/exception', 'another/one');
if (in_array($url, $start, true)) {
    $path = './cache/';
    $file = 'index.html';
} else {
    $pos = strpos(strrev($url), '/');
    $pos = ($pos ? (strlen($url) - ($pos - 1)) : false);
    $path = './cache' . substr($url, 0, $pos, '/'));
    $file = substr(strrchr(rtrim($url, '/'), '/'), 1) . '.html';
}
if (!in_array($url, $blacklisted, true)) {
    $parts = explode('/', $path);
    foreach($parts as $part) {
        $dir = (isset($dir) ? $dir . $part . '/' : $part . '/' );
        if (!file_exists($dir)) {
            @mkdir($dir, 0777);
        }
    }
    file_put_contents($path . '/' . $file, $html);
}

对于缓存无效,我在POST请求时手动调用@unlink('./cache/comment/id/'. $id . '.html');来编辑内容。有时glob()类型的递归删除嵌套的资源url。

对于页面的动态部分,比如客人和登录用户的不同的菜单,我只是使用了一些Javascript和cookie来确定要显示的内容。