air_wang 发表于 2009-3-26 12:09:10

kndb session 用法简介

CI的session有点问题,很多时候需要挂载其他的扩展session,坛子里网友推荐了kndb session,我大致用了一下,下面简单介绍下用法:
第一步:建立系统数据库,这里假设数据库名是test;
第二步:建立存储session的数据表sessions
CREATE TABLE sessions (                                                                                                                           
session_id varchar(32) NOT NULL,                                                                                                                  
session_last_access int(10) unsigned,                                                                                                            
session_data text,                                                                                                                              
PRIMARY KEY (session_id)                                                                                                                        
);
第三步:修改CI文件夹/system/application/config/config.php
$config['sess_cookie_name']            = 'CISESSION';
$config['sess_expiration']            = 7200;
$config['sess_encrypt_cookie']      = FALSE;
$config['sess_table_name']            = 'sessions';
$config['sess_match_ip']            = TRUE;
$config['sess_match_useragent']      = TRUE;
$config['sess_use_database']      = TRUE;
$config['sess_time_to_update']      = 300;
第四步:在CI文件夹/system/application/libraries下建立文件Session.php,输入以下内容
<?phpif (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Code Igniter
*
* An open source application development framework for PHP 4.3.2 or newer
*
* @package   CodeIgniter
* @author      Elise Bosse
* @copyright   Copyright (c) 2008, E.Bosse
* @license   http://www.codeignitor.com/user_guide/license.html
* @link      http://www.codeigniter.com
* @since       Version 1.2
* @filesource
*/

// ------------------------------------------------------------------------

/**
* Session class using native PHP session features and hardened against session fixation.
* Non-database part is based upon Dariusz Debowczyk's Native session library with some updates.
* The DB part makes use of PHP's session_set_save_handler() functionality
* This library is written for PHP 5 but it could be altered a bit to make it work in PHP4
*
* @package   CodeIgniter
* @subpackageLibraries
* @category    Sessions
* @author      Elise Bosse
* @link      http://www.codeigniter.com/user_guide/libraries/sessions.html
* @class linkhttp://codeigniter.com/wiki/KNDB_Session/
*/

/**
* If using a database, create the following database table and make sure config file is set properly
*
* CREATE TABLE sessions (
* session_id varchar(32) NOT NULL,
* session_last_access int(10) unsigned,
* session_data text,
* PRIMARY KEY (session_id)
* );
*/

class MY_Session {

private $_lifetime;
private $_sess_id_ttl;
private $_match_ip;
private $_match_useragent;
private $_sess_db;
private $_useDB;
private $_sess_table;
private $_flash_key = 'flash'; // prefix for "flash" variables (eg. flash:new:message)

function __construct()
{
    $this->object =& get_instance();

    // set config variables
    $this->_lifetime = $this->object->config->item('sess_expiration');
    $this->_sess_id_ttl = $this->object->config->item('sess_time_to_update');
    $this->_match_ip = $this->object->config->item('sess_match_ip');
    $this->_match_useragent = $this->object->config->item('sess_match_useragent');
    $this->_useDB = $this->object->config->item('sess_use_database');
    $this->_sess_table = $this->object->config->item('sess_table_name');

    log_message('debug', "Session Class Initialized");

    $this->_sess_run();
}

/**
   * Starts up the session system for current request
   */
function _sess_run()
{
    // Set session table and register this object as the session handler, if using databases
    if ($this->_useDB == TRUE) {
      session_set_save_handler(array(&$this, "_open"), array(&$this, "_close"), array(&$this, "_read"),
                   array(&$this, "_write"),array(&$this, "_destroy"),array(&$this, "_gc"));
    }

    session_start();

    // if no lifetime set in config, set to 2 years
    if (!is_numeric($this->_lifetime) || $this->_lifetime <= 0) {
      $this->_lifetime = (60*60*24*365*2);
    }

    // if no session ID regeneration time set in config, set to 30 minutes
    if (!is_numeric($this->_sess_id_ttl) || $this->_sess_id_ttl <= 0) {
      $this->_sess_id_ttl = 1800;
    }

    // check if session has expired
    if ($this->_session_expired()) {
      $this->sess_destroy();
      return FALSE;
    }

    // match IP address if necessary
    if ($this->_match_ip == TRUE) {
      if ($this->_ips_match() == FALSE) {
    $this->sess_destroy();
    return FALSE;
      }
    }
   
    // match user agent if necessary
    if ($this->_match_useragent == TRUE) {
      if ($this->_useragents_match() == FALSE) {
    $this->sess_destroy();
    return FALSE;
      }
    }

    // regenerate session id if necessary
    // session data stays the same, but old session storage is destroyed
    if ( $this->_sess_id_expired() ) {      
      $this->regenerate_id();
    }

    // delete old flashdata (from last request)
    $this->_flashdata_sweep();

    // mark all new flashdata as old (data will be deleted before next request)
    $this->_flashdata_mark();

    // finally, set last access time to now
    $this->set_userdata('sess_last_access', time());
}

/**
   * Checks if session has expired
   */
function _session_expired()
{
    // if this is the first time coming in, initialize access time
    if (!$this->userdata('sess_last_access')) {
      $this->set_userdata('sess_last_access', time());
      return FALSE;
    }

    $delta = time() - $this->userdata('sess_last_access');

    if ($delta>=$this->_lifetime ) {
      return true;
    }

    return false;
}

/**
   * Checks if stored IP matches current IP
   */
function _ips_match() {
    // if this is the first time coming in, initialize IP address
    if (!$this->userdata('sess_ip_address')) {
      $this->set_userdata('sess_ip_address',$this->object->input->ip_address());
      return TRUE;
    }   

    return $this->userdata('sess_ip_address') == $this->object->input->ip_address();
}

/**
   * Checks if stored user agent matches current user agent
   */
function _useragents_match() {
    // if this is the first time coming in, initialize user agent
    if (!$this->userdata('sess_useragent')) {
      $this->set_userdata('sess_useragent', trim(substr($this->object->input->user_agent(), 0, 50)));
      return TRUE;
    }   

    return $this->userdata('sess_useragent') == trim(substr($this->object->input->user_agent(), 0, 50));
}


/**
   * Checks if session id needs regenerating
   */
function _sess_id_expired()
{
    // if this is the first time coming in, initialize regenerated time
    if (!$this->userdata('sess_last_regenerated')) {
      $this->set_userdata('sess_last_regenerated', time());
      return false;
    }

    $delta = time() - $this->userdata('sess_last_regenerated');

    if ( $delta >=$this->_sess_id_ttl ) {
      return true;
    }

    return false;
}


/**
   * Regenerates session id
   */
function regenerate_id()
{
    // regenerate session id and store it
    // $delete_old_session parameter works in PHP5 only!
    session_regenerate_id(TRUE);

    // update the session generation time
    $this->set_userdata('sess_last_regenerated', time());
}


/**
   * Destroys the session and erases session storage
   */
function sess_destroy()
{
    session_unset();
    if ( isset( $_COOKIE ) )
      {
    //@@@ was having trouble just using setcookie() because it wasn't unsetting fast enough
    unset($_COOKIE);
    setcookie(session_name(), '', time()-42000, '/'); //@@@
      }

    session_destroy();
}


/**                                                                                                                                          
   * returns the session id of the currentsession                                                                                             
   */
function get_sess_id() {
    return session_id();
}


/**
   * Reads given session attribute value: single variable, element of single dimensional array, or property of object
   * I was kind of of two minds about whether the object bit should be implemented
   * so you can take out that logic if you wish
   */   
function userdata($item, $subitem=null)
{
    // this item is in an array
    if ($subitem) {
      if ($subitem == 'session_id'){ //added forbackward-compatibility                                                                        
      return session_id();
      } else {
      // array vs. object: handled differently
      if (isset($_SESSION[$item])) {
          if (is_array($_SESSION[$item])) return (!isset($_SESSION[$item][$subitem])) ? false : $_SESSION[$item][$subitem];
          if (is_object($_SESSION[$item])) return(!isset($_SESSION[$item]->$subitem)) ? false :$_SESSION[$item]->$subitem;
          return false;
      }
      }
    }

    // this item is not in an array
    else {
      if($item == 'session_id'){ //added for backward-compatibility
      return session_id();
      } else {
      return ( ! isset($_SESSION[$item])) ? false : $_SESSION[$item];
      }
    }

}

/**
   * Returns all session data
   */   
function all_userdata()
{
    if (isset($_SESSION['session_id'])) { //added for backward-compatibility
      $_SESSION['session_id'] = session_id();
    }
    return $_SESSION;
}

/**
   * Sets session attributes to the given values
   */
function set_userdata($newdata = array(), $newval = '')
{
    if (is_string($newdata))
      {
    $newdata = array($newdata => $newval);
      }

    if (count($newdata) > 0)
      {
    foreach ($newdata as $key => $val)
      {
      $_SESSION[$key] = $val;
      }
      }
}

/**
   * Erases given session attributes
   */
function unset_userdata($newdata = array())
{
    if (is_string($newdata))
      {
    $newdata = array($newdata => '');
      }

    if (count($newdata) > 0)
      {
    foreach ($newdata as $key => $val)
      {
      unset($_SESSION[$key]);
      }
      }
}


/**
* Sets "flash" data which will be available only in next request (then it will
* be deleted from session). You can use it to implement "Save succeeded" messages
* after redirect.
*/
function set_flashdata($key, $value)
{
    $flash_key = $this->_flash_key.':new:'.$key;
    $this->set_userdata($flash_key, $value);
}

/**
   * Keeps existing "flash" data available to next request.
   */
function keep_flashdata($key)
{
    $old_flash_key = $this->_flash_key.':old:'.$key;
    $value = $this->userdata($old_flash_key);

    $new_flash_key = $this->_flash_key.':new:'.$key;
    $this->set_userdata($new_flash_key, $value);
}

/**
   * Returns "flash" data for the given key.
   */
function flashdata($key)
{
    $flash_key = $this->_flash_key.':old:'.$key;
    return $this->userdata($flash_key);
}

/**
   * PRIVATE: Internal method - marks "flash" session attributes as 'old'
   */
function _flashdata_mark()
{
    foreach ($_SESSION as $name => $value)
      {
    $parts = explode(':new:', $name);
    if (is_array($parts) && count($parts) == 2)
      {
      $new_name = $this->_flash_key.':old:'.$parts;
      $this->set_userdata($new_name, $value);
      $this->unset_userdata($name);
      }
      }
}

/**
   * PRIVATE: Internal method - removes "flash" session marked as 'old'
   */
function _flashdata_sweep()
{
    foreach ($_SESSION as $name => $value)
      {
    $parts = explode(':old:', $name);
    if (is_array($parts) && count($parts) == 2 && $parts == $this->_flash_key)
      {
      $this->unset_userdata($name);
      }
      }
}




/************* DATABASE METHODS ***************/
function _open()
{
    if ($this->_sess_db = mysql_connect($this->object->db->hostname,
                  $this->object->db->username,
                  $this->object->db->password)) {
      return mysql_select_db($this->object->db->database, $this->_sess_db);
    }
   
    return FALSE;
}

function _close()
{
    if ($this->_sess_db) {
      return mysql_close($this->_sess_db);
    }

    return TRUE;
}

function _read($id)
{
    $id = mysql_real_escape_string($id);
   
    $sql = "SELECT session_data FROM $this->_sess_table WHERE session_id = '$id'";
   
    if ($result = mysql_query($sql, $this->_sess_db)) {
      if (mysql_num_rows($result)) {
    $record = mysql_fetch_assoc($result);
   
    return $record['session_data'];
      }
    }
   
    return '';
}

function _write($id, $data)
{
    $access = time();

    $id = mysql_real_escape_string($id);
    $access = mysql_real_escape_string($access);
    $data = mysql_real_escape_string($data);
   
    $sql = "REPLACE INTO $this->_sess_table VALUES ('$id', '$access', '$data')";
   
    return mysql_query($sql, $this->_sess_db);
}

function _destroy($id)
{
    $id = mysql_real_escape_string($id);
   
    $sql = "DELETE FROM $this->_sess_table WHERE session_id = '$id'";

    return mysql_query($sql, $this->_sess_db) or die("failed to delete<br>");
}

function _gc($max)
{
    $old = time() - $max;
    $old = mysql_real_escape_string($old);
   
    $sql = "DELETE FROM $this->_sess_table WHERE session_last_access < '$old'";
   
    return mysql_query($sql, $this->_sess_db);
}


}
第五步:修改CI文件夹/system/application/config/autoload.php
加入自动装载类库database和session,类似以下配置
$autoload['libraries'] = array('database','session');
这里主要介绍使用数据库存储session的方法,如果需要用文件型的session,只要简单的在CI的配置文件里设置:
$config['sess_use_database']    = False;
kndb session的wiki地址是:http://codeigniter.com/wiki/KNDB_Session/

wangy 发表于 2014-9-29 17:03:34

必须要支持!

Hex 发表于 2009-3-26 14:55:30

讲解清晰,好教程,转移到教程区!

PS: 我修改了一下语法加亮

moorland 发表于 2009-3-26 17:57:54

多谢:victory:

Alex_Best 发表于 2009-5-31 16:41:57

ci的session很困惑···

yayagao 发表于 2009-6-12 10:17:29

困惑啊。session类够呛啊……

huapiaoxiang 发表于 2009-6-27 13:51:06

修改了以的用法应该也是一样的吧?

zhoulei 发表于 2009-6-27 14:16:40

刚还在问Hex kndb session怎么用了收下:victory:

phelps_liu 发表于 2009-7-31 16:36:21

Session 确实有问题啊

phelps_liu 发表于 2009-7-31 16:36:43

我还能发帖:lol

lichaoying 发表于 2009-8-3 14:15:31

支持一下
页: [1] 2 3 4
查看完整版本: kndb session 用法简介