zoukankan      html  css  js  c++  java
  • php下自动缓存功能的实现

    使用方法非常简单,只需包含一个文件即可...

    <?php

    /**
     * auto_cache.php 实现智能的自动缓存。
     * 使用办法极其简单:
     * 在需要实现缓存功能的页面 require 'auto_cache.php'; 就ok了
     * @author rains31@gmail.com
     */
    //本文件不允许直接访问,必须定义RAINS_ROOT才能使用
    if(!defined('RAINS_ROOT'))die('access denied!');
    //存放缓存的根目录,最好是放到/tmp目录,尤其是虚拟主机用户,因为/tmp目录不占自己的主页空间啊:)
    define('CACHE_ROOT', dirname(__FILE__).'/cache');
    //缓存文件的生命期,单位秒,86400秒是一天
    define('CACHE_LIFE', 86400);
    //缓存文件的扩展名,千万别用 .php .asp .jsp .pl 等等
    define('CACHE_SUFFIX','.cache');
    //清除全部缓存文件所需的密码md5值
    define('CLEAN_ALL_PASSWORD','60645f9c8e8862725798d9dccf07c885');
    //缓存文件名
    $file_name  = md5($_SERVER['REQUEST_URI']).CACHE_SUFFIX;
    //缓存目录,根据md5的前两位把缓存文件分散开。避免文件过多。如果有必要,可以用第三四位为名,再加一层目录。
    //256个目录每个目录1000个文件的话,就是25万个页面。两层目录的话就是65536*1000=六千五百万。
    //不要让单个目录多于1000,以免影响性能。
    $cache_dir  = CACHE_ROOT.'/'.substr($file_name,0,2);
    //缓存文件
    $cache_file = $cache_dir.'/'.$file_name;
     
    //回调函数,当程序结束时自动调用此函数
    function auto_cache($contents)
    {
        global $cache_file;
        //加一个清空缓存的选择
        $fp = fopen($cache_file,'wb');
        flock($fp,LOCK_EX);
        fwrite($fp, $contents);
        flock($fp,LOCK_UN);
        fclose($fp);
        chmod($cache_file,0777);
        //生成新缓存的同时,自动删除所有的老缓存。以节约空间。
        clean_cache();
        return $contents;
    }
     
    function clean_cache($clean_all=false)
    {
        if($clean_all)
        {
            if(!isset($_SERVER['PHP_AUTH_USER']) || md5($_SERVER['PHP_AUTH_PW'])!=CLEAN_ALL_PASSWORD)
            {
                header('WWW-Authenticate: Basic realm="需要身份验证"');
                header('HTTP/1.0 401 Unauthorized');
                sleep(3);
                die('清空全部缓存需要密码');
            }
            else
            {
                sleep(1);
            }
        }
        chdir(CACHE_ROOT);
        foreach (glob("*/*".CACHE_SUFFIX) as $file)
        {
           if($clean_all || time()-filemtime($file)>CACHE_LIFE)
           {
               unlink($file);
           }
        }
    }
     
    //GET方式请求才缓存,POST之后一般都希望看到最新的结果
    if($_SERVER['REQUEST_METHOD']=='GET')
    {
        //如果缓存文件存在,并且没有过期,就把它读出来。
        if(file_exists($cache_file) && time()-filemtime($cache_file)<CACHE_LIFE)
        {
            $fp = fopen($cache_file,'rb');
            flock($fp,LOCK_SH);
            fpassthru($fp);
            flock($fp,LOCK_UN);
            fclose($fp);
            die;
        }
        elseif(!file_exists($cache_dir))
        {
            if(!file_exists(CACHE_ROOT))
            {
                mkdir(CACHE_ROOT,0777);
                chmod(CACHE_ROOT,0777);
            }
            mkdir($cache_dir,0777);
            chmod($cache_dir,0777);
        }
        //缓存不能只建立一半,需要无视用户的取消。
        ignore_user_abort();
        //回调函数 auto_cache
        ob_start('auto_cache');
    }
    else
    {
        //不是GET的请求就删除缓存文件。
        if(file_exists($cache_file))unlink($cache_file);
        //如果post了clean_all就清空全部缓存
        if(isset($_POST['clean_all']))clean_cache(true);
    }
    ?>
  • 相关阅读:
    C语言 va_start 宏
    C语言 strcat_s 函数
    C语言 strcat 函数
    C语言 memcpy_s 函数
    C语言 memcpy 函数
    C语言 strcpy_s 函数
    C语言 strcpy 函数
    C语言 sizeof 函数
    c++实现扫雷游戏 初学
    .Net vs .Net Core,我该如何选择?看这一篇文章就够了
  • 原文地址:https://www.cnblogs.com/kuyuecs/p/1340353.html
Copyright © 2011-2022 走看看