codeigniter读取数据库的公共配置并全局缓存的实现方案

来源:互联网 发布:windows平板好用吗 编辑:程序博客网 时间:2024/06/07 05:04

本文转自:http://blog.csdn.net/zm2714/article/details/8058218


引言

学习CodeIgniter大概有几天了。从第一天了解后,对CI情有独钟,比较符合我的风格。其实一直以来对框架这块不太敏感。自己长时间的开发,也有一套自己的开发风格和习惯。但是这年头,你说你不会框架,你都不好意思说你是做开发的。所以就选择一个框架来弥补这个缺点了。去年也接触过thinkPHP,但是对于分组这块,始终感觉理解和掌握不到位,由于时间关系,也就没有深入下去。这次也是因为在国庆节前有位客户要求用框架开发。所以,也到了不得不掌握一门框架的地步了。于是国庆期间,在家偶尔看了一下官方文档,甚是喜欢。这不,为了一展身手,决定将以前的一个项目转为CI框架模式。一切顺利,只是有一个问题让我一时无法解决,于是在“CI中国论坛”上求助,经过百度与GOOGLE的帮助,终于解决了这个心病,于是在此做个记录,以做纪念。

问题来源

在一般的开发模式中,网站都有一个全局配置,而正常情况下,这些配置都保存在数据库中的一个表中。我的项目是通过一个公共文件里,从数据库表中读取配置信息,并存到缓存中(memcache),在需要的位置都包含这个文件,也就是说,只要第一次从数据库读取数据,那么该数据就被缓存了,以后就可以直接在缓存中取数据,而不需要每次读数据库。除非该缓存已清空(机器重启的情况下)。

这个公共文件内容如下(为了节约篇幅,代码做了修改,只体现这个思路)

[php] view plain copy
  1. $mem=new Memcache;  
  2. $mem->connect("127.0.0.1",11211);  
  3. $_config_arr=$mem->get('config');  
  4. //$_config_arr='';  
  5. if(!is_array($_config_arr)){  
  6.   //从数据库读取配置文件  
  7.   $query=mysql_query('select webname,domain,default_lang from config where id=1');  
  8.   if(mysql_num_rows($query)){  
  9.     $arr=mysql_fetch_array($query);  
  10.     $mem->set('config',$arr,0,0);  
  11.     $_config_arr=$mem->get('config');  
  12.   }  
  13. }  
  14.   
  15. if(is_array($_config_arr)){  
  16.   $_webname=$_config_arr[webname];  
  17.   $_domain=$_config_arr[domain];  
  18.   $_default_lang=$_config_arr[default_lang];  
  19. }  

解决过程

那么在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、发贴寻求帮助,在尝试测试下终于理顺思路,解决如本篇文章标题所示的问题。在此提供解决方案,欢迎交流,如果有更好方案,也希望与我分享。感谢。

寻求帮助

网友提供帮助内容如下:

[plain] view plain copy
  1. 通过扩展CI_Controller类,增加一个或多个方法,这样在所有的控制器都可以使用这些方法了,就像公用方法了。在这些方法中对数据库进行操作。  
  2. 例如  
  3. MY_Controller类继承于CI_Controller,你的控制器继承于MY_Controller。在MY_Controller中增加个options方法,这个方法对数据库进行操作,以后在每个控制器的方法中都可以使用options()方法获取你需要的信息了。  
  4. (扩展核心类)请看手册,恕我无法一一细说:http://codeigniter.org.cn/user_guide/general/core_classes.html  

解决方案

我的解决方案是:扩展CI_Controller类(文件名:MY_Controller),在该类的构造函数中读取数据库的表的配置信息。将信息通过$this->load->vars($data);设为全局变量。这样只要加载视图,无需传递该$data值即可使用$data里的所有变量信息。($data是一对象)

实现代码

MY_Controller代码如下:

[php] view plain copy
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');  
  2.   
  3. class MY_Controller extends CI_Controller{  
  4.     public function __construct(){  
  5.         parent::__construct();  
  6.         $this->load->driver('cache');  
  7.         $this->load->model('manager_model');  
  8.           
  9.         $_config_arr=$this->cache->memcached->get('config');  
  10.         if(!is_object($_config_arr)){  
  11.             $_config_arr=$this->manager_model->get_config();  
  12.             $this->cache->memcached->save('config',$_config_arr,0);  
  13.         }  
  14.           
  15.         if(is_object($_config_arr)){  
  16.           $data['_webname']=$_config_arr->webname;  
  17.           $data['_domain']=$_config_arr->domain;  
  18.           $data['_default_lang']=$_config_arr->default_lang;  
  19.           $this->load->vars($data);  
  20.         }  
  21.   
  22.     }  
  23. }  
manager_model模型中get_config()方法代码如下:

[php] view plain copy
  1. function get_config(){  
  2.     $query = $this->db->query('select id,webname,domain,default_lang from config where id=1');  
  3.     if($query->num_rows())  
  4.     {  
  5.         return $query->row();  
  6.     }  
  7. }  
控制器中加载config.php视图方法如下:

[php] view plain copy
  1. public function config(){  
  2.     $this->load->view('public/config');//这里无需传递第二个参数。  
  3. }  
config方法中,如果有其它参数,也以通过第二个参数传递。不影响传递$data的值。比如:

[php] view plain copy
  1. public function config(){  
  2.     $data1['title']='这是标题';  
  3.     $data1['keyword']='这是关键字';  
  4.     $this->load->view('public/config',$data1);  
  5. }  
在视图public/config.php文件中,即可以使用$data中所有变量,也可以使用$title和$keyword变量。

相关问题描述

CodeIgniter 用户指南 版本 2.1.0 关于Memcached缓存的使用说明

[plain] view plain copy
  1. Memcached 缓存  
  2.   
  3. 使用分布式 Memcached 服务器 可以通过配置文件: memcached.php 来配置,该文件在 application/config/ 目录下.  
  4.   
  5. All of the functions listed above can be accessed without passing a specific adapter to the driver loader as follows:  
  6.   
  7. $this->load->driver('cache');  
  8. $this->cache->memcached->save('foo', 'bar', 10);  
  9. 若想了解更多关于 Memcached的信息, 请参考 http://php.net/memcached  
来源:http://codeigniter.org.cn/user_guide/drivers/caching.html#dummy

我的CodeIgniter 版本 2.1.2,却在application/config中找不到memcached.php这个配置文件

其实,需要手工在该目录创建,内容默认如下:

[php] view plain copy
  1. $config['memcached'] = array(  
  2.     'hostname'  => '127.0.0.1',  
  3.     'port'      => 11211,  
  4.     'weight'    => 1  
  5. );  

说明:上面的“Cache_memcached.php”中已经有默认的值,该值与上面这个配置文件内容相同。如果你的设置与默认值恰好相同,也可以不用建立memcached.php这个配置文件。如果不同,你也可以直接更改 Cache_memcached.php 文件中的配置值。但是,你一旦建立memcached.php这个配置文件,那么该值将会覆盖 Cache_memcached.php 中的默认值。

Cache_memcached.php代码

[php] view plain copy
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');  
  2. /** 
  3.  * CodeIgniter 
  4.  * 
  5.  * An open source application development framework for PHP 4.3.2 or newer 
  6.  * 
  7.  * @package  CodeIgniter 
  8.  * @author  ExpressionEngine Dev Team 
  9.  * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc. 
  10.  * @license  http://codeigniter.com/user_guide/license.html 
  11.  * @link  http://codeigniter.com 
  12.  * @since  Version 2.0 
  13.  * @filesource 
  14.  */  
  15.   
  16. // ------------------------------------------------------------------------  
  17.   
  18. /** 
  19.  * CodeIgniter Memcached Caching Class 
  20.  * 
  21.  * @package  CodeIgniter 
  22.  * @subpackage Libraries 
  23.  * @category Core 
  24.  * @author  ExpressionEngine Dev Team 
  25.  * @link 
  26.  */  
  27.   
  28. class CI_Cache_memcached extends CI_Driver {  
  29.   
  30.  private $_memcached// Holds the memcached object  
  31.   
  32.  protected $_memcache_conf  = array(  
  33.       'default' => array(  
  34.       'default_host'  => '127.0.0.1',  
  35.       'default_port'  => 11211,  
  36.       'default_weight' => 1  
  37.      )  
  38.     );  
  39.   
  40.  // ------------------------------------------------------------------------  
  41.   
  42.  /** 
  43.   * Fetch from cache 
  44.   * 
  45.   * @param  mixed  unique key id 
  46.   * @return  mixed  data on success/false on failure 
  47.   */  
  48.  public function get($id)  
  49.  {  
  50.   $data = $this->_memcached->get($id);  
  51.   return (is_array($data)) ? $data[0] : FALSE;  
  52.  }  
  53.   
  54.  // ------------------------------------------------------------------------  
  55.   
  56.  /** 
  57.   * Save 
  58.   * 
  59.   * @param  string  unique identifier 
  60.   * @param  mixed  data being cached 
  61.   * @param  int   time to live 
  62.   * @return  boolean  true on success, false on failure 
  63.   */  
  64.  public function save($id$data$ttl = 60)  
  65.  {  
  66.   if (get_class($this->_memcached) == 'Memcached')  
  67.   {  
  68.    return $this->_memcached->set($idarray($data, time(), $ttl), $ttl);  
  69.   }  
  70.   else if (get_class($this->_memcached) == 'Memcache')  
  71.   {  
  72.    return $this->_memcached->set($idarray($data, time(), $ttl), 0, $ttl);  
  73.   }  
  74.   return FALSE;  
  75.  }  
  76.   
  77.  // ------------------------------------------------------------------------  
  78.   
  79.  /** 
  80.   * Delete from Cache 
  81.   * 
  82.   * @param  mixed  key to be deleted. 
  83.   * @return  boolean  true on success, false on failure 
  84.   */  
  85.  public function delete($id)  
  86.  {  
  87.   return $this->_memcached->delete($id);  
  88.  }  
  89.   
  90.  // ------------------------------------------------------------------------  
  91.   
  92.  /** 
  93.   * Clean the Cache 
  94.   * 
  95.   * @return  boolean  false on failure/true on success 
  96.   */  
  97.  public function clean()  
  98.  {  
  99.   return $this->_memcached->flush();  
  100.  }  
  101.   
  102.  // ------------------------------------------------------------------------  
  103.   
  104.  /** 
  105.   * Cache Info 
  106.   * 
  107.   * @param  null  type not supported in memcached 
  108.   * @return  mixed   array on success, false on failure 
  109.   */  
  110.  public function cache_info($type = NULL)  
  111.  {  
  112.   return $this->_memcached->getStats();  
  113.  }  
  114.   
  115.  // ------------------------------------------------------------------------  
  116.   
  117.  /** 
  118.   * Get Cache Metadata 
  119.   * 
  120.   * @param  mixed  key to get cache metadata on 
  121.   * @return  mixed  FALSE on failure, array on success. 
  122.   */  
  123.  public function get_metadata($id)  
  124.  {  
  125.   $stored = $this->_memcached->get($id);  
  126.   
  127.   if (count($stored) !== 3)  
  128.   {  
  129.    return FALSE;  
  130.   }  
  131.   
  132.   list($data$time$ttl) = $stored;  
  133.   
  134.   return array(  
  135.    'expire' => $time + $ttl,  
  136.    'mtime'  => $time,  
  137.    'data'  => $data  
  138.   );  
  139.  }  
  140.   
  141.  // ------------------------------------------------------------------------  
  142.   
  143.  /** 
  144.   * Setup memcached. 
  145.   */  
  146.  private function _setup_memcached()  
  147.  {  
  148.   // Try to load memcached server info from the config file.  
  149.   $CI =& get_instance();  
  150.   if ($CI->config->load('memcached', TRUE, TRUE))  
  151.   {  
  152.    if (is_array($CI->config->config['memcached']))  
  153.    {  
  154.     $this->_memcache_conf = NULL;  
  155.   
  156.     foreach ($CI->config->config['memcached'as $name => $conf)  
  157.     {  
  158.      $this->_memcache_conf[$name] = $conf;  
  159.     }  
  160.    }  
  161.   }  
  162.   if (extension_loaded('memcached')){  
  163.    $this->_memcached = new Memcached();  
  164.   }else{  
  165.    $this->_memcached = new Memcache();  
  166.   }  
  167.   
  168.   
  169.  foreach ($this->_memcache_conf as $name => $cache_server)  
  170.  {  
  171.            if ( ! array_key_exists('hostname'$cache_server))  
  172.             {  
  173.   
  174.                // $cache_server['hostname'] = $this->_default_options['default_host']; //坑爹的原代码,没有_default_options属性  
  175.                 $cache_server['hostname'] = $this->_memcache_conf['default']['default_host'];  
  176.             }  
  177.   
  178.             if ( ! array_key_exists('port'$cache_server))  
  179.             {  
  180.   
  181.                // $cache_server['port'] = $this->_default_options['default_port'];//坑爹的原代码,没有_default_options属性  
  182.                 $cache_server['port'] = $this->_memcache_conf['default']['default_port'];  
  183.             }  
  184.   
  185.             if ( ! array_key_exists('weight'$cache_server))  
  186.             {  
  187.   
  188.               //  $cache_server['weight'] = $this->_default_options['default_weight'];//坑爹的原代码,没有_default_options属性  
  189.                 $cache_server['weight'] = $this->_memcache_conf['default']['default_weight'];  
  190.             }  
  191.              //导致如果不配置 config/memcache.php文件,执行到$this->_memcached->addServer($cache_server['hostname'],$cache_server['port']);出错(因为此时语句,相当于$this->_memcached->addServer(‘’,'');然后机器木反应了~  
  192.   
  193.             if (extension_loaded('memcached')){  
  194.                 $this->_memcached->addServer(  
  195.                     $cache_server['hostname'], $cache_server['port'], $cache_server['weight']  
  196.                 );  
  197.             }else{  
  198.                 $this->_memcached->addServer($cache_server['hostname'],$cache_server['port'],TRUE, $cache_server['weight']);  
  199.             }  
  200.     }  
  201.  }  
  202.   
  203.  // ------------------------------------------------------------------------  
  204.   
  205.  /** 
  206.   * Is supported 
  207.   * 
  208.   * Returns FALSE if memcached is not supported on the system. 
  209.   * If it is, we setup the memcached object & return TRUE 
  210.   */  
  211.  public function is_supported()  
  212.  {  
  213.   
  214.   if ( !extension_loaded('memcached') && !extension_loaded('memcache'))  
  215.   {  
  216.    log_message('error''The Memcached Extension must be loaded to use Memcached Cache.');  
  217.   
  218.    return FALSE;  
  219.   }  
  220.   
  221.   $this->_setup_memcached();  
  222.   return TRUE;  
  223.  }  
  224.   
  225.  // ------------------------------------------------------------------------  
  226.   
  227. }  
  228. // End Class  
  229.   
  230. /* End of file Cache_memcached.php */  
  231. /* 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)

[php] view plain copy
  1. $this->_memcached = new Memcached();  
修改为:

[php] view plain copy
  1. if (extension_loaded('memcached')){  
  2.   $this->_memcached = new Memcached();  
  3. }else{  
  4.   $this->_memcached = new Memcache();  
  5. }  
2、原类中没有_default_options属性

由于没有_default_options属性,所以导致_setup_memcached()方法中所有关于此句的代码都要换个方式。也可以建立个_default_options属性。上面代码中是将

[php] view plain copy
  1. $cache_server['hostname'] = $this->_default_options['default_host'];  
更改为

[php] view plain copy
  1. $cache_server['hostname'] = $this->_memcache_conf['default']['default_host'];  
还包括port 和 weight的取值。

3、is_supported() 方法

将原内容:

[php] view plain copy
  1. if ( ! extension_loaded('memcached'))  
修改为:

[php] view plain copy
  1. if ( !extension_loaded('memcached') && !extension_loaded('memcache'))  
这些改动内容都不用多做解释。在这只是将改动部分与原内容做一个说明。
原创粉丝点击