codeigniter讀取數據庫的公共配置並全局緩存的實現方案

引言

學習CodeIgniter大概有幾天了。從第一天瞭解後,對CI情有獨鍾,比較符合個人風格。其實一直以來對框架這塊不太敏感。本身長時間的開發,也有一套本身的開發風格和習慣。可是這年頭,你說你不會框架,你都很差意思說你是作開發的。因此就選擇一個框架來彌補這個缺點了。去年也接觸過thinkPHP,可是對於分組這塊,始終感受理解和掌握不到位,因爲時間關係,也就沒有深刻下去。此次也是由於在國慶節前有位客戶要求用框架開發。因此,也到了不起不掌握一門框架的地步了。因而國慶期間,在家偶爾看了一下官方文檔,甚是喜歡。這不,爲了一展身手,決定將之前的一個項目轉爲CI框架模式。一切順利,只是有一個問題讓我一時沒法解決,因而在「CI中國論壇」上求助,通過百度與GOOGLE的幫助,終於解決了這個心病,因而在此作個記錄,以作記念。php

問題來源

在通常的開發模式中,網站都有一個全局配置,而正常狀況下,這些配置都保存在數據庫中的一個表中。個人項目是經過一個公共文件裏,從數據庫表中讀取配置信息,並存到緩存中(memcache),在須要的位置都包含這個文件,也就是說,只要第一次從數據庫讀取數據,那麼該數據就被緩存了,之後就能夠直接在緩存中取數據,而不須要每次讀數據庫。除非該緩存已清空(機器重啓的狀況下)。html

這個公共文件內容以下(爲了節約篇幅,代碼作了修改,只體現這個思路)mysql

$mem=new Memcache;
$mem->connect("127.0.0.1",11211);
$_config_arr=$mem->get('config');
//$_config_arr='';
if(!is_array($_config_arr)){
  //從數據庫讀取配置文件
  $query=mysql_query('select webname,domain,default_lang from config where id=1');
  if(mysql_num_rows($query)){
    $arr=mysql_fetch_array($query);
    $mem->set('config',$arr,0,0);
    $_config_arr=$mem->get('config');
  }
}

if(is_array($_config_arr)){
  $_webname=$_config_arr[webname];
  $_domain=$_config_arr[domain];
  $_default_lang=$_config_arr[default_lang];
}

解決過程

那麼在CI中我該如何實現呢?

可能想到的有幾個辦法,但這些辦法要麼行不通,要麼太繁瑣。web

一、在入口文件index.php中實現。後瞭解,在此文件中實現沒法加載數據庫。總不能單獨寫個鏈接數據庫這樣的東西吧,就跟一坨屎同樣。sql

二、在helper中寫,helper其實就是 include,可是helper仍然在數據庫加載以前就已加載。數據庫

三、寫一個模型中,而後自動加載該模型,並在模型中將數據寫到緩存中?windows

四、瘋狂百度GOOGLE中....緩存

在「CI中國論壇」瞭解到,CI只支持memcached,而不支持memcache,而memcached是在unix中的,windows系統上只有memcache。而遺憾的是,我用的就是windows,猶如晴天霹靂。我想,若是CI不支持,也只有經過$mem=new Memcache;這樣的方式寫了。就是感受彆扭。幸虧,找到了解決辦法。具體訪問:服務器

CI system/libraries/Cache/drivers/memcached.php 兼容 memcache,memcached擴展app

解決了CI不支持memcache的問題。解決方案:將上面連接中的代碼整理好覆蓋原文件內容。(爲何要整理?若是直接複製,因爲網頁緣由,有一段本是註釋程序卻未被註釋,將會致使出錯。本篇末尾提供memcached.php代碼,你也能夠直接拷貝並替換原文件。)

五、發貼尋求幫助,在嘗試測試下終於理順思路,解決如本篇文章標題所示的問題。在此提供解決方案,歡迎交流,若是有更好方案,也但願與我分享。感謝。

尋求幫助

網友提供幫助內容以下:

經過擴展CI_Controller類,增長一個或多個方法,這樣在全部的控制器均可以使用這些方法了,就像公用方法了。在這些方法中對數據庫進行操做。
例如
MY_Controller類繼承於CI_Controller,你的控制器繼承於MY_Controller。在MY_Controller中增長個options方法,這個方法對數據庫進行操做,之後在每一個控制器的方法中均可以使用options()方法獲取你須要的信息了。
(擴展核心類)請看手冊,恕我沒法一一細說:http://codeigniter.org.cn/user_guide/general/core_classes.html

解決方案

個人解決方案是:擴展CI_Controller類(文件名:MY_Controller),在該類的構造函數中讀取數據庫的表的配置信息。將信息經過$this->load->vars($data);設爲全局變量。這樣只要加載視圖,無需傳遞該$data值便可使用$data裏的全部變量信息。($data是一對象)

實現代碼

MY_Controller代碼以下:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class MY_Controller extends CI_Controller{
	public function __construct(){
		parent::__construct();
		$this->load->driver('cache');
		$this->load->model('manager_model');
		
		$_config_arr=$this->cache->memcached->get('config');
		if(!is_object($_config_arr)){
			$_config_arr=$this->manager_model->get_config();
			$this->cache->memcached->save('config',$_config_arr,0);
		}
		
		if(is_object($_config_arr)){
		  $data['_webname']=$_config_arr->webname;
		  $data['_domain']=$_config_arr->domain;
		  $data['_default_lang']=$_config_arr->default_lang;
		  $this->load->vars($data);
		}

	}
}
manager_model模型中get_config()方法代碼以下:

function get_config(){
	$query = $this->db->query('select id,webname,domain,default_lang from config where id=1');
	if($query->num_rows())
	{
		return $query->row();
	}
}
控制器中加載config.php視圖方法以下:

public function config(){
	$this->load->view('public/config');//這裏無需傳遞第二個參數。
}
config方法中,若是有其它參數,也以經過第二個參數傳遞。不影響傳遞$data的值。好比:

public function config(){
	$data1['title']='這是標題';
	$data1['keyword']='這是關鍵字';
	$this->load->view('public/config',$data1);
}
在視圖public/config.php文件中,便可以使用$data中全部變量,也可使用$title和$keyword變量。

相關問題描述

CodeIgniter 用戶指南 版本 2.1.0 關於Memcached緩存的使用說明

Memcached 緩存

使用分佈式 Memcached 服務器 能夠經過配置文件: memcached.php 來配置,該文件在 application/config/ 目錄下.

All of the functions listed above can be accessed without passing a specific adapter to the driver loader as follows:

$this->load->driver('cache');
$this->cache->memcached->save('foo', 'bar', 10);
若想了解更多關於 Memcached的信息, 請參考 http://php.net/memcached
來源:http://codeigniter.org.cn/user_guide/drivers/caching.html#dummy

個人CodeIgniter 版本 2.1.2,卻在application/config中找不到memcached.php這個配置文件

其實,須要手工在該目錄建立,內容默認以下:

$config['memcached'] = array(
	'hostname'	=> '127.0.0.1',
	'port'		=> 11211,
	'weight'	=> 1
);

說明:上面的「Cache_memcached.php」中已經有默認的值,該值與上面這個配置文件內容相同。若是你的設置與默認值剛好相同,也能夠不用創建memcached.php這個配置文件。若是不一樣,你也能夠直接更改 Cache_memcached.php 文件中的配置值。可是,你一旦創建memcached.php這個配置文件,那麼該值將會覆蓋 Cache_memcached.php 中的默認值。

Cache_memcached.php代碼

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP 4.3.2 or newer
 *
 * @package  CodeIgniter
 * @author  ExpressionEngine Dev Team
 * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc.
 * @license  http://codeigniter.com/user_guide/license.html
 * @link  http://codeigniter.com
 * @since  Version 2.0
 * @filesource
 */

// ------------------------------------------------------------------------

/**
 * CodeIgniter Memcached Caching Class
 *
 * @package  CodeIgniter
 * @subpackage Libraries
 * @category Core
 * @author  ExpressionEngine Dev Team
 * @link
 */

class CI_Cache_memcached extends CI_Driver {

 private $_memcached; // Holds the memcached object

 protected $_memcache_conf  = array(
      'default' => array(
      'default_host'  => '127.0.0.1',
      'default_port'  => 11211,
      'default_weight' => 1
     )
    );

 // ------------------------------------------------------------------------

 /**
  * Fetch from cache
  *
  * @param  mixed  unique key id
  * @return  mixed  data on success/false on failure
  */
 public function get($id)
 {
  $data = $this->_memcached->get($id);
  return (is_array($data)) ? $data[0] : FALSE;
 }

 // ------------------------------------------------------------------------

 /**
  * Save
  *
  * @param  string  unique identifier
  * @param  mixed  data being cached
  * @param  int   time to live
  * @return  boolean  true on success, false on failure
  */
 public function save($id, $data, $ttl = 60)
 {
  if (get_class($this->_memcached) == 'Memcached')
  {
   return $this->_memcached->set($id, array($data, time(), $ttl), $ttl);
  }
  else if (get_class($this->_memcached) == 'Memcache')
  {
   return $this->_memcached->set($id, array($data, time(), $ttl), 0, $ttl);
  }
  return FALSE;
 }

 // ------------------------------------------------------------------------

 /**
  * Delete from Cache
  *
  * @param  mixed  key to be deleted.
  * @return  boolean  true on success, false on failure
  */
 public function delete($id)
 {
  return $this->_memcached->delete($id);
 }

 // ------------------------------------------------------------------------

 /**
  * Clean the Cache
  *
  * @return  boolean  false on failure/true on success
  */
 public function clean()
 {
  return $this->_memcached->flush();
 }

 // ------------------------------------------------------------------------

 /**
  * Cache Info
  *
  * @param  null  type not supported in memcached
  * @return  mixed   array on success, false on failure
  */
 public function cache_info($type = NULL)
 {
  return $this->_memcached->getStats();
 }

 // ------------------------------------------------------------------------

 /**
  * Get Cache Metadata
  *
  * @param  mixed  key to get cache metadata on
  * @return  mixed  FALSE on failure, array on success.
  */
 public function get_metadata($id)
 {
  $stored = $this->_memcached->get($id);

  if (count($stored) !== 3)
  {
   return FALSE;
  }

  list($data, $time, $ttl) = $stored;

  return array(
   'expire' => $time + $ttl,
   'mtime'  => $time,
   'data'  => $data
  );
 }

 // ------------------------------------------------------------------------

 /**
  * Setup memcached.
  */
 private function _setup_memcached()
 {
  // Try to load memcached server info from the config file.
  $CI =& get_instance();
  if ($CI->config->load('memcached', TRUE, TRUE))
  {
   if (is_array($CI->config->config['memcached']))
   {
    $this->_memcache_conf = NULL;

    foreach ($CI->config->config['memcached'] as $name => $conf)
    {
     $this->_memcache_conf[$name] = $conf;
    }
   }
  }
  if (extension_loaded('memcached')){
   $this->_memcached = new Memcached();
  }else{
   $this->_memcached = new Memcache();
  }


 foreach ($this->_memcache_conf as $name => $cache_server)
 {
           if ( ! array_key_exists('hostname', $cache_server))
            {

               // $cache_server['hostname'] = $this->_default_options['default_host']; //坑爹的原代碼,沒有_default_options屬性
                $cache_server['hostname'] = $this->_memcache_conf['default']['default_host'];
            }

            if ( ! array_key_exists('port', $cache_server))
            {

               // $cache_server['port'] = $this->_default_options['default_port'];//坑爹的原代碼,沒有_default_options屬性
                $cache_server['port'] = $this->_memcache_conf['default']['default_port'];
            }

            if ( ! array_key_exists('weight', $cache_server))
            {

              //  $cache_server['weight'] = $this->_default_options['default_weight'];//坑爹的原代碼,沒有_default_options屬性
                $cache_server['weight'] = $this->_memcache_conf['default']['default_weight'];
            }
             //致使若是不配置 config/memcache.php文件,執行到$this->_memcached->addServer($cache_server['hostname'],$cache_server['port']);出錯(由於此時語句,至關於$this->_memcached->addServer(‘’,'');而後機器木反應了~

            if (extension_loaded('memcached')){
                $this->_memcached->addServer(
                    $cache_server['hostname'], $cache_server['port'], $cache_server['weight']
                );
            }else{
                $this->_memcached->addServer($cache_server['hostname'],$cache_server['port'],TRUE, $cache_server['weight']);
            }
    }
 }

 // ------------------------------------------------------------------------

 /**
  * Is supported
  *
  * Returns FALSE if memcached is not supported on the system.
  * If it is, we setup the memcached object & return TRUE
  */
 public function is_supported()
 {

  if ( !extension_loaded('memcached') && !extension_loaded('memcache'))
  {
   log_message('error', 'The Memcached Extension must be loaded to use Memcached Cache.');

   return FALSE;
  }

  $this->_setup_memcached();
  return TRUE;
 }

 // ------------------------------------------------------------------------

}
// End Class

/* End of file Cache_memcached.php */
/* Location: ./system/libraries/Cache/drivers/Cache_memcached.php */

代碼分析摘要

1、memcached->addServer與memcache->addServer區別

http://www.php.net/manual/zh/memcached.addserver.php

http://www.php.net/manual/zh/memcache.addserver.php

2、與原文件改動部分

一、_setup_memcached()方法修改

原內容:(由於只考慮了memcached)

$this->_memcached = new Memcached();
修改成:

 if (extension_loaded('memcached')){
   $this->_memcached = new Memcached();
 }else{
   $this->_memcached = new Memcache();
 }
二、原類中沒有_default_options屬性

因爲沒有_default_options屬性,因此致使_setup_memcached()方法中全部關於此句的代碼都要換個方式。也能夠創建個_default_options屬性。上面代碼中是將

$cache_server['hostname'] = $this->_default_options['default_host'];
更改成

$cache_server['hostname'] = $this->_memcache_conf['default']['default_host'];
還包括port 和 weight的取值。

三、is_supported() 方法

將原內容:

if ( ! extension_loaded('memcached'))
修改成:

if ( !extension_loaded('memcached') && !extension_loaded('memcache'))
這些改動內容都不用多作解釋。在這只是將改動部分與原內容作一個說明。
相關文章
相關標籤/搜索