zoukankan      html  css  js  c++  java
  • 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'))
    这些改动内容都不用多做解释。在这只是将改动部分与原内容做一个说明。




  • 相关阅读:
    03_ if 练习 _ little2big
    uva 11275 3D Triangles
    uva 12296 Pieces and Discs
    uvalive 3218 Find the Border
    uvalive 2797 Monster Trap
    uvalive 4992 Jungle Outpost
    uva 2218 Triathlon
    uvalive 3890 Most Distant Point from the Sea
    uvalive 4728 Squares
    uva 10256 The Great Divide
  • 原文地址:https://www.cnblogs.com/moqiang02/p/4061159.html
Copyright © 2011-2022 走看看