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




  • 相关阅读:
    Spring Cloud的小改进(五)
    国内最火的10款Java开源项目,都是国人开发,CMS居多
    创建服务的注册与发现 Eureka (四)
    Eureka的的概述(三)
    sourcetree 跳过首次登录
    基于IDEA工具 lombok 的使用
    面试总结
    Spring Cloud的概述(二)
    微服务的概述(一)
    原子性 CAS算法
  • 原文地址:https://www.cnblogs.com/moqiang02/p/4061159.html
Copyright © 2020-2023  润新知