【问题标题】:caching whole php output to static html using htaccess and modrewrite使用 htaccess 和 modrewrite 将整个 php 输出缓存到静态 html
【发布时间】:2015-11-26 20:21:27
【问题描述】:

我有一个 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 存在吗?加载它

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

unique 可以使用什么?

【问题讨论】:

  • 请详细说明哪些页面已经创建了一个完整的输出缓存文件
  • @JasonMcCreary 基于我选择的 Url/route 如果要缓存页面,缓存文件会与一个小的有效负载一起保存(然后用于检查它是否已到期)。我没有写当前的缓存系统,我认为这与问题无关。

标签: php .htaccess mod-rewrite caching


【解决方案1】:

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

让我们从 .htaccess
开始 以将每个丢失的文件重定向到您的目录索引的方式编写您的 .htaccess。 它可能看起来像这样

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

现在如果没有找到调用的页面,您将收到对 index.php 的请求。

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

您可以即时创建目录。

index.php
在将数据推回浏览器之前,请确保将其全部保存在一个变量中。您可以使用 include 函数来做到这一点。 请参阅this page 上的示例 5。

根据您的目录级别保存数据。

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

最后,这只是基本的想法,你必须自己弄清楚tweeks和tricks。

【讨论】:

  • 谢谢,我对 Php 方面没有任何问题,是 .htaccess/mod_rewrite 语法我不知道,我想了解详细信息。虽然我可以使用目录和子目录,但我更愿意将所有内容都保存在一个目录中。我想一个简单的mod_rewrite slashdash 就可以了
  • 是的,有很多关于这个的问题。
【解决方案2】:

最后还是很简单的,虽然我不得不使用Url的相同目录和子目录,但我记得的WordPress插件是supercache和我使用的mod_rewrite几乎一样。

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

.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());
    }
}

【讨论】:

    【解决方案3】:

    几年前我用过类似的东西,并设法找到了来源。我的.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 来确定要显示的内容。

    非常简单,但非常有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-26
      • 2012-06-23
      • 2020-03-17
      相关资源
      最近更新 更多