codeigniter讀取數據庫的公共配置并全局緩存的實現方案
來源:程序員人生 發布時間:2014-10-14 01:52:49 閱讀次數:6507次
引言
學習CodeIgniter大概有幾天了。從第一天了解后,對CI情有獨鐘,比較符合我的風格。其實一直以來對框架這塊不太敏感。自己長時間的開發,也有一套自己的開發風格和習慣。但是這年頭,你說你不會框架,你都不好意思說你是做開發的。所以就選擇一個框架來彌補這個缺點了。去年也接觸過thinkPHP,但是對于分組這塊,始終感覺理解和掌握不到位,由于時間關系,也就沒有深入下去。這次也是因為在國慶節前有位客戶要求用框架開發。所以,也到了不得不掌握一門框架的地步了。于是國慶期間,在家偶爾看了一下官方文檔,甚是喜歡。這不,為了一展身手,決定將以前的一個項目轉為CI框架模式。一切順利,只是有一個問題讓我一時無法解決,于是在“CI中國論壇”上求助,經過百度與GOOGLE的幫助,終于解決了這個心病,于是在此做個記錄,以做紀念。
問題來源
在一般的開發模式中,網站都有一個全局配置,而正常情況下,這些配置都保存在數據庫中的一個表中。我的項目是通過一個公共文件里,從數據庫表中讀取配置信息,并存到緩存中(memcache),在需要的位置都包含這個文件,也就是說,只要第一次從數據庫讀取數據,那么該數據就被緩存了,以后就可以直接在緩存中取數據,而不需要每次讀數據庫。除非該緩存已清空(機器重啟的情況下)。
這個公共文件內容如下(為了節約篇幅,代碼做了修改,只體現這個思路)
$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中我該如何實現呢?
可能想到的有幾個辦法,但這些辦法要么行不通,要么太繁瑣。
1、在入口文件index.php中實現。后了解,在此文件中實現無法加載數據庫。總不能單獨寫個連接數據庫這樣的東西吧,就跟一坨屎一樣。
2、在helper中寫,helper其實就是 include,但是helper仍然在數據庫加載之前就已加載。
3、寫一個模型中,然后自動加載該模型,并在模型中將數據寫到緩存中?
4、瘋狂百度GOOGLE中....
在“CI中國論壇”了解到,CI只支持memcached,而不支持memcache,而memcached是在unix中的,windows系統上只有memcache。而遺憾的是,我用的就是windows,猶如晴天霹靂。我想,如果CI不支持,也只有通過$mem=new Memcache;這樣的方式寫了。就是感覺別扭。幸好,找到了解決辦法。具體訪問:
CI system/libraries/Cache/drivers/memcached.php 兼容 memcache,memcached擴展
解決了CI不支持memcache的問題。解決方案:將上面鏈接中的代碼整理好覆蓋原文件內容。(為什么要整理?如果直接復制,由于網頁原因,有一段本是注釋程序卻未被注釋,將會導致出錯。本篇末尾提供memcached.php代碼,你也可以直接拷貝并替換原文件。)
5、發貼尋求幫助,在嘗試測試下終于理順思路,解決如本篇文章標題所示的問題。在此提供解決方案,歡迎交流,如果有更好方案,也希望與我分享。感謝。
尋求幫助
網友提供幫助內容如下:
通過擴展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 */
代碼分析摘要
一、memcached->addServer與memcache->addServer區別
http://www.php.net/manual/zh/memcached.addserver.php
http://www.php.net/manual/zh/memcache.addserver.php
二、與原文件改動部分
1、_setup_memcached()方法修改
原內容:(因為只考慮了memcached)
$this->_memcached = new Memcached();
修改為:
if (extension_loaded('memcached')){
$this->_memcached = new Memcached();
}else{
$this->_memcached = new Memcache();
}
2、原類中沒有_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的取值。
3、is_supported() 方法
將原內容:
if ( ! extension_loaded('memcached'))
修改為:
if ( !extension_loaded('memcached') && !extension_loaded('memcache'))
這些改動內容都不用多做解釋。在這只是將改動部分與原內容做一個說明。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈