引言

学习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读取数据库的公共配置并全局缓存的实现方案的更多相关文章

  1. spring读取数据库的配置信息(url、username、password)时的<bean>PropertyPlaceholderConfigurer的用法

    用法1: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://w ...

  2. 新浪SAE云平台下使用codeigniter的数据库配置

    新浪SAE云平台下使用codeigniter的数据库配置 投稿:shichen2014 字体:[增加 减小] 类型:转载 这篇文章主要介绍了新浪SAE云平台下使用codeigniter的数据库配置,主 ...

  3. Oracle 数据库监听配置和服务

    -- 补充说明 如果要远程连接192.168.10.44上的oracle,那么192.168.10.44服务器必须启动TNSListener.(配置文件 listener.ora) PLSQL Dev ...

  4. Oracle 远程链接oracle数据库服务器的配置

    远程链接oracle数据库服务器的配置 by:授客 QQ:1033553122 原理: 一.Oracle客户端与服务器端的通讯机制 1.OracleNet协议 如下图所示,Oracle通过Oracle ...

  5. # spring boot + mybatis 读取数据库

    spring boot + mybatis 读取数据库 创建数据库 use testdb; drop table if exists t_city; create table t_city( id i ...

  6. 读取数据库数据,并将数据整合成3D饼图在jsp中显示

    首先我将生成饼图的方法独立写成一个PieChar.java类,详细代码如下:(数据库需要自己建,如有需要的话) import java.io.IOException; import java.sql. ...

  7. oracle数据库的TNS配置

    TNS简要介绍与应用 Oracle中TNS的完整定义:transparence Network Substrate透明网络底层,监听服务是它重要的一部分,不是全部,不要把TNS当作只是监听器. TNS ...

  8. PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [2] 首页 APP 接口开发方案 ① 读取数据库方式

    方案一:读取数据库方式 从数据库读取信息→封装→生成接口数据 应用场景: 数据时效性比较高的系统 方案二:读取缓存方式 从数据库获取信息(第一次设置缓存或缓存失效时)→封装(第一次设置缓存或缓存失效时 ...

  9. jdbc读取数据库图片文件

    package 读取大文件.read; import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.I ...

随机推荐

  1. 小程序上传多图片多附件多视频 c#后端

    前言: 最近在研究微信小程序,本人自己是C#写后端的;感觉小程序挺好玩的,就自己研究了一下:刚好今天又给我需求,通过小程序上传多图 然后C#后端保存到服务器: 用NET明白 前端上传需要用到流,然后就 ...

  2. ECS服务里或者阿里云服务器的二级域名设置方法

    我们要实现的效果是,xuxinshuai.abc.com ,具体怎么实现,看下面的流程 第一步:备案域名要有,假如就是www.abc.com 第二步:网站的服务器是IIS的情况下,在部署网站时,需要设 ...

  3. Mysql避免重复插入记录方法

    一.mysql replace用法 1.replace into  replace into table (id,name) values('1','aa'),('2','bb')  此语句的作用是向 ...

  4. 在有主分支和个人分支情况下的TFS使用方法

    从事.NET开发的资深童鞋一定都知道VS有自带的代码管理工具TFS(Team Foundation Server ),但是开发萌新可能就不太了解了,下面我就介绍一下这个工具以及它的一些常用操作. TF ...

  5. 快速了解“云原生”(Cloud Native)和前端开发的技术结合点

    欢迎访问网易云社区,了解更多网易技术产品运营经验. 后端视角,结合点就是通过前端流控缓解后端的压力,提升系统响应能力. 从一般意义理解,Cloud Native 是后端应用的事情,要搞的是系统解耦.横 ...

  6. 为什么 kubernetes 天然适合微服务 (3)

    此文已由作者刘超授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验 四.Kubernetes 本身就是微服务架构 基于上面这十个设计要点,我们再回来看 Kubernetes,会发现 ...

  7. linux下利用httpd搭建tomcat集群,实现负载均衡

    公司使用运营管理平台是单点tomcat,使用量大,或者导出较大的运营数据时,会造成平台不可用,现在需要搭建tomcat集群,调研后,决定使用apache的httpd来搭建tomcat集群.以下是搭建步 ...

  8. kali linux之edb--CrossFire缓冲区溢出

    漏洞的罪恶根源------变量,数据与代码边界不清,开发人员对用户输入没做过滤,或者过滤不严 如这个脚本,写什么,显示什么,但是加上:,|,&&,后面加上系统命令,就执行命令了 缓冲区 ...

  9. Spring之BeanFactory与ApplicationConText

    :BeanFactory基本的工厂解析,管理,实例化所有容器内的bean的接口,spring中所有解析配置文件的类都直接或者间接实现该接口ApplicationContext接口implements ...

  10. HDU6308-2018ACM暑假多校联合训练1011-Time Zone

    题目大意就是给你UTC-8时区的时间 让你求对应时区的时间 哇 这个题 看似简单,但是一开始怎么都过不了啊 同学用自己写的read过了,后来看了一下各位大佬说改成分钟随便过,就随便过了 Problem ...