codeigniter读取数据库的公共配置并全局缓存的实现方案
引言
学习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'))
这些改动内容都不用多做解释。在这只是将改动部分与原内容做一个说明。
codeigniter读取数据库的公共配置并全局缓存的实现方案的更多相关文章
- spring读取数据库的配置信息(url、username、password)时的<bean>PropertyPlaceholderConfigurer的用法
用法1: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://w ...
- 新浪SAE云平台下使用codeigniter的数据库配置
新浪SAE云平台下使用codeigniter的数据库配置 投稿:shichen2014 字体:[增加 减小] 类型:转载 这篇文章主要介绍了新浪SAE云平台下使用codeigniter的数据库配置,主 ...
- Oracle 数据库监听配置和服务
-- 补充说明 如果要远程连接192.168.10.44上的oracle,那么192.168.10.44服务器必须启动TNSListener.(配置文件 listener.ora) PLSQL Dev ...
- Oracle 远程链接oracle数据库服务器的配置
远程链接oracle数据库服务器的配置 by:授客 QQ:1033553122 原理: 一.Oracle客户端与服务器端的通讯机制 1.OracleNet协议 如下图所示,Oracle通过Oracle ...
- # spring boot + mybatis 读取数据库
spring boot + mybatis 读取数据库 创建数据库 use testdb; drop table if exists t_city; create table t_city( id i ...
- 读取数据库数据,并将数据整合成3D饼图在jsp中显示
首先我将生成饼图的方法独立写成一个PieChar.java类,详细代码如下:(数据库需要自己建,如有需要的话) import java.io.IOException; import java.sql. ...
- oracle数据库的TNS配置
TNS简要介绍与应用 Oracle中TNS的完整定义:transparence Network Substrate透明网络底层,监听服务是它重要的一部分,不是全部,不要把TNS当作只是监听器. TNS ...
- PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [2] 首页 APP 接口开发方案 ① 读取数据库方式
方案一:读取数据库方式 从数据库读取信息→封装→生成接口数据 应用场景: 数据时效性比较高的系统 方案二:读取缓存方式 从数据库获取信息(第一次设置缓存或缓存失效时)→封装(第一次设置缓存或缓存失效时 ...
- jdbc读取数据库图片文件
package 读取大文件.read; import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.I ...
随机推荐
- 小程序上传多图片多附件多视频 c#后端
前言: 最近在研究微信小程序,本人自己是C#写后端的;感觉小程序挺好玩的,就自己研究了一下:刚好今天又给我需求,通过小程序上传多图 然后C#后端保存到服务器: 用NET明白 前端上传需要用到流,然后就 ...
- ECS服务里或者阿里云服务器的二级域名设置方法
我们要实现的效果是,xuxinshuai.abc.com ,具体怎么实现,看下面的流程 第一步:备案域名要有,假如就是www.abc.com 第二步:网站的服务器是IIS的情况下,在部署网站时,需要设 ...
- Mysql避免重复插入记录方法
一.mysql replace用法 1.replace into replace into table (id,name) values('1','aa'),('2','bb') 此语句的作用是向 ...
- 在有主分支和个人分支情况下的TFS使用方法
从事.NET开发的资深童鞋一定都知道VS有自带的代码管理工具TFS(Team Foundation Server ),但是开发萌新可能就不太了解了,下面我就介绍一下这个工具以及它的一些常用操作. TF ...
- 快速了解“云原生”(Cloud Native)和前端开发的技术结合点
欢迎访问网易云社区,了解更多网易技术产品运营经验. 后端视角,结合点就是通过前端流控缓解后端的压力,提升系统响应能力. 从一般意义理解,Cloud Native 是后端应用的事情,要搞的是系统解耦.横 ...
- 为什么 kubernetes 天然适合微服务 (3)
此文已由作者刘超授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验 四.Kubernetes 本身就是微服务架构 基于上面这十个设计要点,我们再回来看 Kubernetes,会发现 ...
- linux下利用httpd搭建tomcat集群,实现负载均衡
公司使用运营管理平台是单点tomcat,使用量大,或者导出较大的运营数据时,会造成平台不可用,现在需要搭建tomcat集群,调研后,决定使用apache的httpd来搭建tomcat集群.以下是搭建步 ...
- kali linux之edb--CrossFire缓冲区溢出
漏洞的罪恶根源------变量,数据与代码边界不清,开发人员对用户输入没做过滤,或者过滤不严 如这个脚本,写什么,显示什么,但是加上:,|,&&,后面加上系统命令,就执行命令了 缓冲区 ...
- Spring之BeanFactory与ApplicationConText
:BeanFactory基本的工厂解析,管理,实例化所有容器内的bean的接口,spring中所有解析配置文件的类都直接或者间接实现该接口ApplicationContext接口implements ...
- HDU6308-2018ACM暑假多校联合训练1011-Time Zone
题目大意就是给你UTC-8时区的时间 让你求对应时区的时间 哇 这个题 看似简单,但是一开始怎么都过不了啊 同学用自己写的read过了,后来看了一下各位大佬说改成分钟随便过,就随便过了 Problem ...