• CodeIgniter网站静态化管理系统


    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的可行宜用的静态缓存系统已经建立完毕



  • 相关阅读:
    js菜单特效分享(1)
    用泛型的IEqualityComparer接口去重复项 .
    jquery一些有用的插件
    JQuery Tree插件——zTree v3.0 beta 发布
    泛型和linq
    js如何隐藏表格的行与列
    34个漂亮的应用程序后台管理界面
    解决Visual Studio setup cannot run in compatibility mode的错误
    html文本框(input)不保存缓存记录
    第九章:第九章:XML文档集成Axd向导
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3481617.html
Copyright © 2020-2023  润新知