1. 程式人生 > >檔案快取瞭解下

檔案快取瞭解下

檔案快取就是指把快取資料儲存到檔案系統也就是硬碟中,大家都知道與記憶體相比,硬碟是屬於速度比較慢的儲存裝置,為什麼我們要使用這個呢???

原因很簡單,磁碟容量大,可以存放足夠多的資料,現在常規的硬碟已經進入到了TB級別,而記憶體還處於GB級別,並且呢,磁碟的價格遠遠低於記憶體,它還比記憶體更加的穩定和可靠,最起碼斷電後資料不會丟失,儲存也是比較簡單,還有就是固態硬碟的出現,使得硬碟的讀寫速度得到了極大的提升,最後就是擴充套件方面了,我們可以使用磁碟陣列、分散式處理等進行大規模的儲存和管理,相比較來說,貌似確實是硬碟價效比更高些。

檔案快取機制的邏輯很清晰,模板的作用之一就是把動態的PHP動態程式碼編譯成靜態的HTML檔案,當下次讀取的時候不會再經過編譯,我們來看一個簡單的模板引擎進行檔案快取的程式碼例項,首先是模板類:

//Template.php
class Template{
    private $arrayConfig = array(
        'suffix' => '.m', //模板檔案的字尾
        'template_dir' => 'template/', //模板所在的資料夾
        'compile_dir' => 'cache/', //模板編譯後存放的目錄
        'html' => false, //是否需要編譯為靜態的HTML檔案
        'suffix_cache' => '.html', //編譯檔案的字尾
        'cache_time' => 3600, //多長時間自動更新,單位,秒
        'php' => true,
        'cache_control' => 'control.dat',
        'debug' => false
    );
    private $value = array();
    private $compile_tool;
    public $file; //模板名稱
    public $debug = array();
    private $control_data = array();
    static private $instance = null;
    public function __construct($arrayConfig = array())
    {
        $this->debug['begin'] = microtime(true);
        $this->arrayConfig = $arrayConfig + $this->arrayConfig;
        $this->get_path();
        if(!is_dir($this->arrayConfig['template_dir'])){
            exit('template');
        }
        if(!is_dir($this->arrayConfig['compile_dir'])){
            exit('compile');
        }
        include ('CompileClass.php');
    }

    public function get_path()
    {
        $this->arrayConfig['template_dir'] = strtr(realpath($this->arrayConfig['template_dir']),'\\','/')."/";
        $this->arrayConfig['compile_dir'] = strtr(realpath($this->arrayConfig['compile_dir']),'\\','/')."/";
    }

    public static function get_instance()
    {
        if(is_null(self::$instance)){
            self::$instance = new Template();
        }

        return self::$instance;
    }

    public function set_config($key,$value=null)
    {
        if(is_array($key)){
            $this->arrayConfig = $key + $this->arrayConfig;
        }else{
            $this->arrayConfig[$key] = $value;
        }
    }

    public function get_config($key=null)
    {
        if($key){
            return $this->arrayConfig[$key];
        }else{
            return $this->arrayConfig;
        }
    }

    public function assign($key,$value)
    {
        $this->value[$key] = $value;
    }

    public function assign_arr($array)
    {
        if(is_array($array)){
            foreach ($array as $item=>$value) {
                $this->value[$item] = $value;
            }
        }
    }

    public function path()
    {
        return $this->arrayConfig['template_dir'].$this->file.$this->arrayConfig['suffix'];
    }

    public function need_cache()
    {
        return $this->arrayConfig['html'];
    }

    public function re_cache($file)
    {
        $flag = false;
        $cache_file = $this->arrayConfig['compile_dir'].md5($file).'.html';
        if($this->arrayConfig['html'] == true){
            $time_flag = (time()
[email protected]
($cache_file)) < $this->arrayConfig['cache_time'] ? true : false; if(is_file($cache_file) && filesize($cache_file) > 1 && $time_flag){ $flag = true; }else{ $flag = false; } } return $flag; } public function show($file) { $this->file = $file; if(!is_file($this->path())){ exit('there is nothing to make'); } $compile_file = $this->arrayConfig['compile_dir'].md5($file).".php"; $cache_file = $this->arrayConfig['compile_dir'].md5($file).".html"; if($this->re_cache($file) === false){ $this->debug['cached'] = 'false'; $this->compile_tool = new CompileClass($this->path(),$compile_file,$this->arrayConfig); if($this->need_cache()){ ob_start(); } extract($this->value,EXTR_OVERWRITE); if (!is_file($compile_file) || filemtime($compile_file) < filemtime($this->path())) { $this->compile_tool->vars = $this->value; $this->compile_tool->compile(); include $compile_file; }else{ include ($compile_file); } if($this->need_cache()) { $message = ob_get_contents(); file_put_contents($cache_file,$message); } }else{ readfile($cache_file); $this->debug['cached'] = true; } $this->debug['spend'] = microtime(true)-$this->debug['begin']; $this->debug['count'] = count($this->value); $this->debug_info(); } public function debug_info() { if ($this->arrayConfig['debug'] == true) { echo PHP_EOL.'———debug info———'.PHP_EOL; echo "程式執行日期:".date("Y-m-d H:i:s").PHP_EOL; echo "模板解析耗時:".$this->debug['spend']."秒".PHP_EOL; echo "模板包含標籤數目:".$this->debug['count'].PHP_EOL; echo "是否使用靜態快取:".$this->debug['cached'].PHP_EOL; echo "模板引擎例項引數:"; var_dump($this->get_config()); } } public function clean($path=null) { if($path=null) { $path = $this->arrayConfig['compile_dir']; $path = glob($path.'*'.$this->arrayConfig['suffix_cache']); }else{ $path = $this->arrayConfig['compile_dir'].md5($path).".html"; } foreach ($path as $item => $value) { unlink($value); } } }

接下來是編譯類:

//CompileClass.php
class CompileClass{
    private $template;
    private $content;
    private $compile;
    private $left = '{';
    private $right = '}';
    private $value = array();
    private $T_P = array();
    private $T_R = array();

    public function __construct($template,$compile_file,$config)
    {
        $this->template = $template;
        $this->compile = $compile_file;
        $this->content = file_get_contents($template);
        if ($config['php'] == false) {
            $this->T_P[] = '#<\?(=|php|)(.+?)\?>#is';
            $this->T_R[] = '&lt;?\\1\\2?&gt';
        }
        $this->T_P[] = '#\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}#';
        $this->T_P[] = '#\{(loop|foreach)\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)}#';
        $this->T_P[] = '#\{\/(loop|foreach|if)}#i';
        $this->T_P[] = '#\{([K|V])\}#';
        $this->T_P[] = '#\{if(.*?)\}#i';
        $this->T_P[] = '#\{(else if|elseif)(.*?)\}#i';
        $this->T_P[] = '#\{else\}#i';
        $this->T_P[] = '#\{(\#|\*)(.*?)(\#|\*)\}#';
        $this->T_P[] = '#if\(\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)#';

        $this->T_R[] = "<?php echo \$this->value['\\1'];?>";
        $this->T_R[] = "<?php foreach(\$this->value['\\2'] as \$K => \$this->value['V']){?>";
        $this->T_R[] = "<?php } ?>";
        $this->T_R[] = "<?php echo \$\\1;?>";
        $this->T_R[] = "<?php if(\\1){ ?>";
        $this->T_R[] = "<?php }else if(\\2){ ?>";
        $this->T_R[] = "<?php }else{ ?>";
        $this->T_R[] = " ";
        $this->T_R[] = "if(\$this->value['\\1']";
    }

    public function compile()
    {
        $this->c_var2();
        $this->c_static_file();
        file_put_contents($this->compile,$this->content);
    }

    public function c_var2()
    {
        $this->content = preg_replace($this->T_P,$this->T_R,$this->content);
    }

    public function c_static_file()
    {
        $this->content = preg_replace('#\{\!(.*?)\!\}#','<script src=\\1'.'?t='.time().' ></script>',$this->content);
    }

    public function set($name,$value)
    {
        $this->$name = $value;
    }

    public function get($name)
    {
        return $this->$name;
    }
}

然後是模板檔案:

//asd.m
<html>
{!like.js!}
{$data},{$person}
<ul>
    {loop$b}<li>{$V}</li>{/loop}
</ul>
{if$data == 'abc'}
abc
{elseif$data == 'def'}
def
{else}
{$data}
{/if}
{#############################################}
123456——
</html>

最後就是呼叫的程式碼:

//test.php
header('Content-type:text/html;charset=utf-8');
include 'Template.php';
$tpl = new Template(array('php'=>true,'debug'=>true));
$tpl->assign("data","hello word");
$tpl->assign("person","cafe cat");
$tpl->assign("pai",3.14);
$arr = array(1,2,3,4,5,"hat",7);
$tpl->assign('b',$arr);
$tpl->show('asd');
die;

目錄結構如下:

模板檔案放在這個位置:

最後我們會在下圖位置看到編譯後的檔案:

從某種意義上來看的話,資料庫也可以看做是優化過的、高效的檔案儲存的一種,我們對於變動少的,體積比較大的資料可以使用檔案儲存,反之,資料庫比較合適,資料庫比檔案儲存高階的地方就是,它解決了檔案儲存中很難解決的資料同步和鎖的問題。所以說,是用什麼儲存,看大家的意思的,最重要的還是因地制宜,實現需求。

好啦,本次記錄就到這裡了。

如果感覺不錯的話,請多多點贊支援哦。。。