ThinkPHP 3.2.3 數據緩存與靜態緩存

ThinkPHP 3.2.3 中手冊中數據緩存的地址是:http://www.kancloud.cn/manual/thinkphp/1835php

靜態緩存的地址是:http://www.kancloud.cn/manual/thinkphp/1839css

 

數據緩存

使用 S 方法進行數據緩存,緩存文件默認的方式是文件緩存(DATA_CACHE_TYPE = File),文件緩存默認的保存路徑是 ./Application/Runtime/Temphtml

當使用默認的緩存方式時,不須要在配置文件中進行配置,直接在控制器中須要緩存數據的地方調用 S 方法便可:thinkphp

S(緩存名,緩存值,緩存時間)數組

例如在 IndexController.class.php(./Application/Home/Controller/IndexController.class.php)要對首頁數據進行緩存:緩存

<?php
namespace Home\Controller;
use Think\Controller;
use Admin\Common\Category;

class IndexController extends Controller { //首頁 public function index(){ if(!$top_cate = S('index_list')) { //讀取頂級欄目 $top_cate = M('cate')->where(array('pid'=>0))->order('sort')->select(); $cate = M('cate')->order('sort')->select(); $bObj = M('blog'); $field = array('id','title','time'); foreach($top_cate as $key=>$val) { $cids = Category::get_children_id($cate,$val['id']); $cids[] = $val['id']; $where = array('cid'=>array('IN',$cids)); $top_cate[$key]['blog'] = $bObj->field($field)->where($where)->order('time DESC')->select(); } //緩存 S('index_list',$top_cate,3600*24);//1天,默認存儲路徑是 ./Application/Home/Runtime/Temp } $this->assign('top_cate',$top_cate); $this->display(); } }

此時 ./Application/Runtime/Temp 中生成了 823c3bcf17c6b7276fa8799355c4c7c8.php服務器

<?php
//000000086400a:7:{i:0;a:5:{s:2:"id";s:1:"1";s:4:"name";s:4:"HTML";s:3:"pid";s:1:"0";s:4:"sort";s:1:"1";s:4:"blog";a:0:{}}i:1;a:5:{s:2:"id";s:1:"3";s:4:"name";s:10:"JavaScript";s:3:"pid";s:1:"0";s:4:"sort";s:1:"3";s:4:"blog";a:1:{i:0;a:3:{s:2:"id";s:1:"1";s:5:"title";s:2:"js";s:4:"time";s:10:"1455438771";}}}i:2;a:5:{s:2:"id";s:1:"4";s:4:"name";s:3:"PHP";s:3:"pid";s:1:"0";s:4:"sort";s:1:"4";s:4:"blog";a:3:{i:0;a:3:{s:2:"id";s:1:"4";s:5:"title";s:20:"thinkphp關聯模型";s:4:"time";s:10:"1456541875";}i:1;a:3:{s:2:"id";s:1:"3";s:5:"title";s:15:"無限極分類";s:4:"time";s:10:"1456541682";}i:2;a:3:{s:2:"id";s:1:"2";s:5:"title";s:6:"對象";s:4:"time";s:10:"1455438885";}}}i:3;a:5:{s:2:"id";s:1:"2";s:4:"name";s:7:"DIV+CSS";s:3:"pid";s:1:"0";s:4:"sort";s:1:"5";s:4:"blog";a:0:{}}i:4;a:5:{s:2:"id";s:1:"5";s:4:"name";s:5:"MySQL";s:3:"pid";s:1:"0";s:4:"sort";s:1:"5";s:4:"blog";a:0:{}}i:5;a:5:{s:2:"id";s:1:"6";s:4:"name";s:5:"Linux";s:3:"pid";s:1:"0";s:4:"sort";s:1:"6";s:4:"blog";a:0:{}}i:6;a:5:{s:2:"id";s:1:"8";s:4:"name";s:6:"其餘";s:3:"pid";s:1:"0";s:4:"sort";s:1:"7";s:4:"blog";a:0:{}}}
?>
View Code

 

若是要改變緩存方式,例如再也不把緩存存入文件,而是存入 Memcached 中,該項目中 PHP 的 Memcached 擴展是 Memcached:ide

 

此時能夠經過修改配置文件 ./Applicaiton/Home/Common/Conf/conf.php,添加:memcached

    'DATA_CACHE_TYPE'=>'Memcached',
    'PERSISTENTID' => 'mlm_cache',//持久連接標示
    'MEMCACHED_HOST' => '127.0.0.1', //可數組形式
    'MEMCACHED_PORT' => '11211',//可數組形式
    'MEMECACHED_WEIGHT' => 0,//權重

注:Memcached 的驅動能夠在 http://www.thinkphp.cn/extend/559.html 進行下載並放到 ./ThinkPHP/Library/Think/Cache/Driver/Memcached.class.php:fetch

<?php

namespace Think\Cache\Driver;

use Think\Cache;

defined('THINK_PATH') or exit();

/**
 * Memcache緩存驅動
 */
Class Memcached extends Cache {

    public function __construct($options = array()) {
        if (!extension_loaded('memcached')) {
            throw_exception(L('_NOT_SUPPERT_') . ':memcached');
        }
        $servers = array();
        $persistent_id = C('PERSISTENTID') ? C('PERSISTENTID') : null;

        $this->options = $options;
        $this->options['expire'] = isset($options['expire']) ? $options['expire'] : C('DATA_CACHE_TIME');
        $this->options['prefix'] = isset($options['prefix']) ? $options['prefix'] : C('DATA_CACHE_PREFIX');
        $host = C('MEMCACHED_HOST') ? C('MEMCACHED_HOST') : '127.0.0.1';
        $port = C('MEMCACHED_PORT') ? C('MEMCACHED_PORT') : 11211;
        $weight = C('MEMECACHED_WEIGHT') ? C('MEMECACHED_WEIGHT') : 1;
        $weight_is_arr = is_array($weight);


        if (is_array($host)) {
            if (!is_array($port)) {
                throw_exception('Memcached服務器IP和端口號要一一對應');
            }
            if ($weight_is_arr && count($weight) != count($host)) {
                throw_exception('Memcached服務器IP和權重值要一一對應');
            }
            foreach ($host as $key => $value) {
                $servers[] = array($value, $port[$key], $weight_is_arr ? $weight[$key] : $weight);
            }
        } else {
            if (is_array($port)) {
                foreach ($port as $key => $value) {
                    $servers[] = array($host, $value, $weight_is_arr ? $weight[$key] : $weight);
                }
            } else {
                $servers[] = array($host, $port, $weight_is_arr ? $weight[0] : $weight);
            }
        }
        $this->handler = new \Memcached($persistent_id);
        $this->handler->addServers($servers);
//        $serverList = $this->handler->getServerList();
//        var_dump($serverList);
//        var_dump($this->handler->getStats());
//        var_dump($this->handler->getOption());
//        var_dump($this->handler->getVersion());
// p($serverList);
    }

    /**
     * 讀取緩存
     * @access public
     * @param string $name 緩存變量名
     * @return mixed
     */
    public function get($name) {
        N('cache_read', 1);
        return $this->handler->get($this->options['prefix'] . $name);
    }

    /**
     * 讀取多個元素值
     * @param  array  $keys [要讀取的元素key數組]
     * @return [boolean]       [返回值]
     */
    public function getMulti($keys = array()) {
        if (empty($keys))
            return '';
        N('cache_read', 1);
        return $this->handler->getMulti($keys);
    }

    /**
     * 寫入緩存
     * @access public
     * @param string $name 緩存變量名
     * @param mixed $value  存儲數據
     * @param integer $expire  有效時間(秒)
     * @return boolen
     */
    public function set($name, $value, $expire = 0) {
        N('cache_write', 1);
        if (is_null($expire)) {
            $expire = $this->options['expire'];
        }
        $name = $this->options['prefix'] . $name;
        if ($this->handler->set($name, $value, $expire)) {
            return true;
        }
        return false;
    }

    /**
     * 寫入多個元素
     * @param [array] $items  [要寫入的健/值元素數組]
     * @param [int] $expire [有效時間(秒)]
     */
    public function setMulti($items, $expire = 0) {
        N('cache_write', 1);
        if (is_null($expire)) {
            $expire = $this->options['expire'];
        }
        $name = $this->options['prefix'] . $name;

        if ($this->handler->setMulti($items, $expire)) {
            return true;
        }
        return false;
    }

    /**
     * 添加一個元素,若是這個元素已經存在,則失敗
     * @param [string]  $key    [要添加元素的key]
     * @param [string]  $value  [要添加元素的值]
     * @param integer $expire [有效時間]
     * @return boolean
     */
    public function add($key, $value, $expire = 0) {
        N('cache_write', 1);
        return $this->handler->add($key, $value, $expire);
    }

    /**
     * 替換已存在key下的元素,若是不存在此key則失敗
     * @param  [string]  $key    [要替換的key]
     * @param  [string]  $value  [要替換的值]
     * @param  integer $expire [有效時間]
     * @return [boolean]          
     */
    public function replace($key, $value, $expire = 0) {
        N('cache_write', 1);
        return $this->handler->replace($key, $value, $expire);
    }

    /**
     * 刪除緩存
     * @access public
     * @param string $name 緩存變量名
     * @return boolen
     */
    public function rm($name) {
        $name = $this->options['prefix'] . $name;
        return $this->handler->delete($name);
    }

    /**
     * 清除緩存
     * @access public
     * @return boolen
     */
    public function clear() {
        return $this->handler->flush();
    }

}
Memcached.class.php

 

同時 ./Application/Home/Controller/IndexController.class.php 修改成:

<?php
namespace Home\Controller;
use Think\Controller;
use Admin\Common\Category;
use Think\Cache\Driver\Memcached;

class IndexController extends Controller {
    //首頁
    public function index(){
        
        if(!$top_cate = S('index_list')) {

            //讀取頂級欄目
            $top_cate = M('cate')->where(array('pid'=>0))->order('sort')->select();
            $cate = M('cate')->order('sort')->select();
            $bObj = M('blog');
            $field = array('id','title','time');
            
            foreach($top_cate as $key=>$val) {
                $cids = Category::get_children_id($cate,$val['id']);
                $cids[] = $val['id'];
                $where = array('cid'=>array('IN',$cids));
                $top_cate[$key]['blog'] = $bObj->field($field)->where($where)->order('time DESC')->select();
            }

            //緩存
            S('index_list',$top_cate,3600*24);//1天,默認存儲路徑是 ./Application/Home/Runtime/Temp 
        }
        
        $this->assign('top_cate',$top_cate);
        $this->display();
    }
}

在服務器端開啓 Memcached,刷新首頁,此時 Runtime/Tmp 下不會再生成緩存文件;

經過 Telnet 客戶端查看 Memcached 服務器中存儲的緩存:

stats items
STAT items:12:number 1
STAT items:12:age 216
STAT items:12:evicted 0
STAT items:12:evicted_nonzero 0
STAT items:12:evicted_time 0
STAT items:12:outofmemory 0
STAT items:12:tailrepairs 0
STAT items:12:reclaimed 0
STAT items:12:expired_unfetched 0
STAT items:12:evicted_unfetched 0
STAT items:12:crawler_reclaimed 0
STAT items:12:crawler_items_checked 0
STAT items:12:lrutail_reflocked 0
END
stats cachedump 12 0
ITEM index_list [898 b; 1456615330 s]
END

(Memcache 查看列出全部key方法:http://www.ttlsa.com/memcache/memcache-list-all-keys/)  

首頁在 Memcached 中的緩存爲 index_list。

 

 

靜態緩存

靜態緩存就相似於一些 CMS 中直接把頁面靜態化,在靜態文件的生存週期內直接訪問靜態的 HTML 文件

Home 模塊的靜態緩存須要在配置文件 ./Application/Home/Common/Conf/config.php 中添加配置:

    //開啓靜態緩存
    'HTML_CACHE_ON'=>true,
    'HTML_CACHE_RULES'=>array(
        
        //給Show控制器的index方法生成緩存,默認的保存位置是 ./Application/Html
        'show:index'=>array('{:module}_{:action}_{id}',10) //參數:緩存文件的名稱,緩存生存週期(0表明永不過時)
    ),

以上配置表示緩存 show 控制器的 index 方法,保存的文件名是 show_index_{id},id 表示 $_GET['id'],也就是說(show 控制器的 index 方法用於查看文章內容頁,經過 URL 傳遞的參數 id 來訪問相應 id 的文章)訪問 id 爲 4 的文章時會生成 show_index_4.html 文件,默認保存在 ./Applicaiton/Html 中

 

控制器 ./Application/Home/Controller/ShowController.class.php:

<?php
namespace Home\Controller;
use Think\Controller;
use Admin\Common\Category;

class ShowController extends Controller{
    //展現頁
    public function index() {
        
        $id = (int)$_GET['id'];
        $where = array('id'=>$id,'del'=>0);
        $field = array('id','title','content','time','cid');
        $blog = M('blog')->field($field)->where($where)->find();
        
        //實體轉換成字符
        $blog['content'] = htmlspecialchars_decode(html_entity_decode($blog['content']));
        $this->blog = $blog;
        
        //麪包屑,經過子分類查詢全部父分類信息
        $cate = M('cate')->order('sort')->select();
        $this->parent = Category::get_parents($cate, $blog['cid']);
         
        $this->display();
    }
    
    
    //點擊次數不緩存
    public function inc_click() {
        $id = (int)$_GET['id'];
        $where = array('id'=>$id);
        //click自增1
        M('blog')->where($where)->setInc('click');//默認自增1 
        $click = M('blog')->where($where)->getField('click');
        echo 'document.write('.$click.')';
    }
}

 

若是在該頁面中有不須要緩存的內容,例如文章的點擊次數,每進行一次訪問,次數加 1,能夠經過 js 的形式來訪問相應的點擊方法,例如視圖文件 ./Application/Home/View/Show/index.html:

<include file='Common:header'/>    
    <link rel="stylesheet" href="__PUBLIC__/Css/show.css" />
    <!--引入ueditor代碼高亮插件-->
    <link rel="stylesheet" href="__ROOT__/Data/ueditor/third-party/SyntaxHighlighter/shCoreDefault.css">
    <script src="__ROOT__/Data/ueditor/third-party/SyntaxHighlighter/shCore.js"></script>
    <!--引入插件結束-->
    <!--使用ueditor代碼高亮插件-->
    <script>
        SyntaxHighlighter.all();
    </script>
    <!--使用ueditor代碼高亮插件結束-->
</head>
<body>
<!--頭部-->
<include file='Common:nav'/>
<!--主體-->
    <div class='main'>
        <div class='main-left'>
            <div class='location'>
                <a href="">首頁</a>>
                <?php $last = count($parent) - 1;?>
                <foreach name="parent" item="v">
                    <a href="{:U('/c_'.$v['id'])}">{$v.name}</a>
                    <if condition="$last neq $key">></if>
                </foreach>
            </div>
            <div class="title">
                <p>{$blog.title}</p>
                <div>
                    <span class='fl'>發佈於:{$blog.time|date="Y年m月d日",###}</span>
                    <span class='fr'>已被閱讀<script src="{:U('Home/Show/inc_click',array('id'=>$blog['id']),'')}"></script></span>
                </div>
            </div>
            <div class='content' style="word-break: break-all;">
                {$blog.content}
            </div>
        </div>
    <!--主體右側-->
    <include file='Common:right'/>
    </div>
<!--底部-->
    <include file='Common:bottom'/>
相關文章
相關標籤/搜索