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. 转:C语言宏定义时#(井号)和##(双井号)的用法

    转自:http://www.cnblogs.com/welkinwalker/archive/2012/03/30/2424844.html#2678295 #在英语里面叫做 pound 在C语言的宏 ...

  2. NAT负载均衡

    NAT(Network Address Translation 网络地址转换)简单地说就是将一个IP地址转换为另一个IP地址,一般用于未经注册的内部地址与合法的.已获注册的Internet IP地址间 ...

  3. IIS会话过期的问题/WCF日志管理

    http://technet.microsoft.com/zh-cn/library/cc725624(v=ws.10).aspx http://msdn.microsoft.com/zh-cn/li ...

  4. Foreman--管理PuppetClient

    一. 环境: 1. server: puppetmaster+activemq+foreman1.3 server1.xxx.com(10.8.1.201) 2. client: fedora 19 ...

  5. Weak Event Patterns

    https://msdn.microsoft.com/en-US/library/aa970850(v=vs.100).aspx In applications, it is possible tha ...

  6. OAF与Windows 7版本不兼容黑屏卡顿问题

    OAF版本比较原始,在Window7中无法应用配色方案,导致黑屏卡顿问题.(在启动OC4J后,Window7的配色方案还是会还原至原始状态) 修改$JDEV_HOME/jdev/bin/jdev.co ...

  7. bzoj4009

    这是一道神题,首先我们不难先到整体二分吧 下面的问题就是,求出对于每个水果,有多少盘子是他的子路径 直接考虑不是很容易,我们换个思路,考虑对于每个盘子,哪些水果能包含它 我们假设盘子a,b,dep[a ...

  8. [原]Unity3D深入浅出 - GUI控件

    Unity的GUI类提供了丰富的界面控件,通过组合这些控件,完成和用户交互的界面. Lable:绘制文本和图片 Box:绘制一个图形框 Button:绘制一个响应单击事件的按钮 RepeatButto ...

  9. Spring整合Hessian

    Spring让Hessian变得不但强大,而且易用,但是易用背后,却有不少陷阱!   这个例子很简单,但实际上的确花费了我超过一小时的时间,排除了种种问题,最后问题终于水落石出.   整合以上篇Hel ...

  10. jenkins+ant+ssh远程部署服务glassfish

    jenkins安装可以参考官网或自己百度,这里不再说明: jenkins版本2.19.2 这里先说一下目的:主要是通过jenkins实现glassfish的部署,源码使用的是svn,编译是使用ant, ...