CodeIgniter本身带了一套静态化系统

使用方法如下:

$this->output->cache( 3 );//每三分钟重新生成一次静态页面

不过这个在系统化的编辑中不方便管理 由此开发者可以自定义一套自己的缓存管理系统

比如加载相关的ctrl + act配置到memcache中以方便配置的查询 及缓存的清理重新生成等

增加数据库表如下

CREATE TABLE `chewu_news` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `delsign` tinyint(3) unsigned NOT NULL,
  `mid` bigint(20) unsigned NOT NULL,
  `comment` varchar(128) DEFAULT NULL,
  `modtime` datetime NOT NULL,
  `addtime` datetime NOT NULL,
  `controller' varchar(128) NOT NULL,
   'action' varchar(128) NOT NULL,
   'minutes' mediumint default 0;
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=138 DEFAULT CHARSET=utf8 COMMENT='缓存管理表;

添加ctrl action到数据库中

/**
  * dev
  * 加载ctrl action到数据库中 只在开发时使用
  */
 public function loadCtrlActIntoDb()
 {
  $this->_load_ctrls_into_db( dirname( dirname( __FILE__  ) ));
 }

//////////////////////////////////////////////////////////////////////////////////
 //load cache info into database
 private function _load_ctrls_into_db( $dir )
 {
  include_once APPPATH . 'utils/TimeUtils.php';
  
  $list = scandir( $dir ); // 得到该文件下的所有文件和文件夹
  foreach( $list as $file)
  { //遍历
   $file_location = $dir . "/" . $file; //生成路径

if( is_file( $file_location ) && (-1 != strstr( $file_location, '.php' ) || -1 != strstr( $file_location, '.PHP' )) )
   {
    //取class
    $iBegin = strpos( $file_location, 'controllers' );
    $iBegin += strlen( 'controllers' );
    $iEnd = strrpos( $file_location, '/' );
    
    $strModel = '';
    $strModel = substr( $file_location, $iBegin + 1, strrpos( $file_location, '.php' ) - $iBegin - 1 );
    
    if( $iBegin != $iEnd )
    { //model为文件夹名+文件名
     $strModel = str_replace( '/', '_', $strModel );
    }
    
    if( 0 === strpos( $strModel, 'learn' ) || 0 === strpos( $strModel, 'test' ) || 0 === strpos( $strModel, 'config' ) )
    {
     continue;
    }
    
    $strClsFile = file_get_contents( $file_location );
    
    $iPos = strpos( $strClsFile, 'class' );
    
    if( false == $iPos )
    { //非类文件
     continue;
    }
    
    $strClsFile = substr( $strClsFile, $iPos );
    
    $arrRes = preg_split( '/public[ ]+function[ ]+/', $strClsFile );
    
    $strCls = $arrRes [0];
    $strCls = preg_replace( '/[ ]+/', ' ', $strCls );
    
    $arrCls = explode( ' ', $strCls );
    $strCtrl = trim( $arrCls [1] );
    
    $iSize = count( $arrRes );
    
    for( $i = 1; $i < $iSize; ++ $i )
    { //
     $strAction = trim( $arrRes [$i] );
     
     $iEnd = strpos( $strAction, '(' );
     
     $strFunc = substr( $strAction, 0, $iEnd );
     
     if( '__construct' != $strFunc && '__destruct' != $strFunc && !isset( $this->objCtrls->$strCtrl->actions [$strFunc] ) )
     {
      //
      $recCtrlAction = array (
        'addtime' => TimeUtils::getFullTime(),
        'modtime' => TimeUtils::getFullTime(),
        'delsign' => MallEnum::DEL_SIGN_NO,
        'mid' => 1,
        'controller' => $strCtrl,
        'action' => $strFunc,
        'minutes' => 0 );
      
      $this->db->insert( TableNames::CHEWU_CACHE_TIME_MGR, $recCtrlAction );
     }
    }
   }

if( is_dir( $file_location ) && $file != "." && $file != ".." )
   { //判断是不是文件夹
    $this->_load_ctrls_into_db( $file_location ); //继续遍历
   }
  }
 
 }

加载ctrl action信息到memcache

private function _loadCtrls( )
 {
  $this->objCtrls = new stdClass();
  
  $query = $this->db->get_where( TableNames::CHEWU_CACHE_TIME_MGR, array (
    'delsign' => MallEnum::DEL_SIGN_NO ) );
  
  $arrRes = $query->result();
  
  foreach( $arrRes as $row)
  {
   if( !isset( $this->objCtrls->{$row->controller} ) )
   {
    $this->objCtrls->{$row->controller} = new stdClass();
   }
   
   $this->objCtrls->{ $row->controller }->actions [$row->action] = $row;
  }
 
 }

/**
  * 加载到内存
  */
 public function loadStaticMgrInfoIntoMem( )
 {
  $this->_loadCtrls();
  
  $this->memcacheutils->set( 'ctrlsInfo', $this->objCtrls, 0 );
  $this->memcacheutils->set( 'bCtrlInfo', 1, 0 );
  
  foreach( $this->objCtrls as $ctrl => $actions)
  {
   if( isset( $actions->actions ) )
   {
    foreach( $actions->actions as $actname => $act)
    {
     $this->memcacheutils->set( MallEnum::CTRL_ACTION . $act->controller . $act->action, $act->minutes, 0 );
    }
   }
  }
  
  echo 'ret=0';
 
 }

之后可开发一管理端 对某些需要的action进行管理

这时使用静态化的访求如下

public function index( )
 {
  $this->output->cache( intval( $this->memcacheutils->get( MallEnum::CTRL_ACTION . __CLASS__ . __FUNCTION__ ) ));
  $this->mallBiz->index();
 }

为了方便管理这里要对CodeIgniter的框架进行一些修改如下(system/core/Output.php):

/**
  * Write a Cache File
  *
  * @access public
  * @param  string
  * @return void
  */
 function _write_cache($output)
 {
  $CI =& get_instance();
  $path = $CI->config->item('cache_path');

$cache_path = ($path == '') ? APPPATH.'cache/' : $path;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//以上为方便管理cache所做的修改

$Rtr = $GLOBALS[ 'RTR' ];
  $cache_path .= $Rtr->fetch_class() . $Rtr->fetch_method() . '/';
  
  if( !is_dir( $cache_path ) )
  {
   mkdir( $cache_path ); 
  }
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
  {
   log_message('error', "Unable to write cache file: ".$cache_path);
   return;
  }

$uri = $CI->config->item('base_url').
    $CI->config->item('index_page').
    $CI->uri->uri_string();

$cache_path .= md5($uri);

if ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE))
  {
   log_message('error', "Unable to write cache file: ".$cache_path);
   return;
  }

$expire = time() + ($this->cache_expiration * 60);

if (flock($fp, LOCK_EX))
  {
   fwrite($fp, $expire.'TS--->'.$output);
   flock($fp, LOCK_UN);
  }
  else
  {
   log_message('error', "Unable to secure a file lock for file at: ".$cache_path);
   return;
  }
  fclose($fp);
  @chmod($cache_path, FILE_WRITE_MODE);

log_message('debug', "Cache file written: ".$cache_path);
 }

/**
  * Update/serve a cached file
  *
  * @access public
  * @param  object config class
  * @param  object uri class
  * @return void
  */
 function _display_cache(&$CFG, &$URI)
 {
  $cache_path = ($CFG->item('cache_path') == '') ? APPPATH.'cache/' : $CFG->item('cache_path');

// Build the file path.  The file name is an MD5 hash of the full URI
  
  $uri = $CFG->item('base_url').
    $CFG->item('index_page').
    $URI->uri_string;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//此为方便管理cache而做的修改

$Rtr = $GLOBALS[ 'RTR' ];
  $cache_path .= $Rtr->fetch_class() . $Rtr->fetch_method() . '/';
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

$filepath = $cache_path . md5($uri);

if ( ! @file_exists($filepath))
  {
   return FALSE;
  }

if ( ! $fp = @fopen($filepath, FOPEN_READ))
  {
   return FALSE;
  }

flock($fp, LOCK_SH);

$cache = '';
  if (filesize($filepath) > 0)
  {
   $cache = fread($fp, filesize($filepath));
  }

flock($fp, LOCK_UN);
  fclose($fp);

// Strip out the embedded timestamp
  if ( ! preg_match("/(\d+TS--->)/", $cache, $match))
  {
   return FALSE;
  }

// Has the file expired? If so we'll delete it.
  if (time() >= trim(str_replace('TS--->', '', $match['1'])))
  {
   if (is_really_writable($cache_path))
   {
    @unlink($filepath);
    log_message('debug', "Cache file has expired. File deleted");
    return FALSE;
   }
  }

// Display the cache
  $this->_display(str_replace($match['0'], '', $cache));
  log_message('debug', "Cache file is current. Sending it to browser.");
  return TRUE;
 }

}

经以上修改后生成的cache不再是以前的只有md5 hash后的文件名 而是每个ctrlaction放在同一个文件夹里这样可以方便cache的管理(比如删除等)

缓存清理方法如下

//ajax方法

public function clearStaticCache()
 {
  $strCtrl = trim( $this->uri->segment( 4 ));
  $strAct = trim( $this->uri->segment( 5 ));
  
  if( $strCtrl === false || $strCtrl == '' ||
   $strAct === false || $strAct == '' )
  {
   show_404();
  }
  
  $strPath = $this->config->item( 'cache_path' ) .  $strCtrl .$strAct;
  
  if( file_exists( $strPath ) )
  {
   $this->load->helper( 'file' );
   
   delete_files( $strPath, true );
   rmdir( $strPath );
  }
  
  echo 'ret=0';
 }

经过以上CodeIgniter的可行宜用的静态缓存系统已经建立完毕

CodeIgniter网站静态化管理系统的更多相关文章

  1. 关于大型网站技术演进的思考(二十一)--网站静态化处理—web前端优化—下【终篇】(13)

    本篇继续web前端优化的讨论,开始我先讲个我所知道的一个故事,有家大型的企业顺应时代发展的潮流开始投身于互联网行业了,它们为此专门设立了一个事业部,不过该企业把这个事业部里的人事成本,系统运维成本特别 ...

  2. 关于大型网站技术演进的思考(十九)--网站静态化处理—web前端优化—上(11)

    网站静态化处理这个系列马上就要结束了,今天我要讲讲本系列最后一个重要的主题web前端优化.在开始谈论本主题之前,我想问大家一个问题,网站静态化处理技术到底是应该归属于web服务端的技术范畴还是应该归属 ...

  3. 关于大型网站技术演进的思考(十三)--网站静态化处理—CSI(5)

    讲完了SSI,ESI,下面就要讲讲CSI了 ,CSI是浏览器端的动静整合方案,当我文章发表后有朋友就问我,CSI技术是不是就是通过ajax来加载数据啊,我当时的回答只是说你的理解有点片面,那么到底什么 ...

  4. 网站静态化处理—web前端优化—下【终篇】(13)

    网站静态化处理—web前端优化—下[终篇](13) 本篇继续web前端优化的讨论,开始我先讲个我所知道的一个故事,有家大型的企业顺应时代发展的潮流开始投身于互联网行业了,它们为此专门设立了一个事业部, ...

  5. 网站静态化处理—web前端优化—中(12)

    网站静态化处理—web前端优化—中(12) Web前端很多优化原则都是从如何提升网络通讯效率的角度提出的,但是这些原则使用的时候还是有很多陷阱在里面,如果我们不能深入理解这些优化原则背后所隐藏的技术原 ...

  6. 网站静态化处理—web前端优化—上

    网站静态化处理—web前端优化—上(11) 网站静态化处理这个系列马上就要结束了,今天我要讲讲本系列最后一个重要的主题web前端优化.在开始谈论本主题之前,我想问大家一个问题,网站静态化处理技术到底是 ...

  7. 网站静态化处理—CSI(5)

    网站静态化处理—CSI(5) 讲完了SSI,ESI,下面就要讲讲CSI了 ,CSI是浏览器端的动静整合方案,当我文章发表后有朋友就问我,CSI技术是不是就是通过ajax来加载数据啊,我当时的回答只是说 ...

  8. 网站静态化处理—web前端优化—上(11)

    网站静态化处理这个系列马上就要结束了,今天我要讲讲本系列最后一个重要的主题web前端优化.在开始谈论本主题之前,我想问大家一个问题,网站静态化处理技术到底是应该归属于web服务端的技术范畴还是应该归属 ...

  9. 思考ASP.NET网站静态化的利与弊

    最近在思考网站要不要进行静态化的问题,在网上收集和整理了有关静态化利与弊的资料,于是写下此博文分享到网络上.由于本人是一名asp.net开发人员,所以本文的观点可能无法涉及到全部方面,但是比较注重于使 ...

随机推荐

  1. Android:使用ViewPager实现左右滑动切换图片 (简单版)

    ViewPager,它是google SDk中自带的一个附加包的一个类, 可以使视图滑动. 步骤: 1.引入android-support-v4.jar包,在主布局里加入 <android.su ...

  2. ArcGIS Runtime for Android开发教程V2.0(2)开发环境配置

    原文地址: ArcGIS Runtime for Android开发教程V2.0(2)开发环境配置 - ArcGIS_Mobile的专栏 - 博客频道 - CSDN.NET http://blog.c ...

  3. 12232 - Exclusive-OR

    12232 - Exclusive-OR 题目大意是可以设定一个点Xp=v,或者Xp^Xq=v,然后查询Xa^Xb^Xc...等于多少. 由于异或操作跟判连通性很类似,这里可以使用并查集来解决,对于X ...

  4. laravel Authentication and Security

    Creating the user modelFirst of all, we need to define the model that is going to be used to represe ...

  5. cisco vpn client for win10 x64 setup package

    win10 x64安装cisco vpn client报错,解决方法如下: 1.卸载以前安装的所有cisco vpn client,并重启电脑. 2.运行winfix.exe 3.安装Global V ...

  6. Scrapy在win7 32位的安装及依赖包

    Scrapy,一个网络爬虫的框架,首先第一步肯定是安装. 参考网上的文章. 安装过程中需要用到pip工具,请自行安装. 1.安装python 这个是必须的,既然都用到scrapy了,肯定已经安装了py ...

  7. js设置datagriad的行移动

    //                    ,//                formatter: function(value,row,index){//                    ...

  8. [POJ 2891] Strange Way to Express Integers

    Strange Way to Express Integers Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 10907 ...

  9. Fiddler的基本介绍

    fiddler 简介: 一款免费且功能强大的数据包抓取软件.它通过代理的方式获取程序http通讯的数据,可以用其检测网页和服务器的交互情况,能够记录所有客户端和服务器间的http请求,支持监视.设置断 ...

  10. java的四舍五入算法

    粗力度的四舍五入为整数 package math; public class MathRoundTest { /** * Math类中提供了三个与取整有关的方法:ceil,floor,round, * ...