前端学PHP之会话Session

前面的话

  Session技术和Cookie类似,都是用来储存使用者的相关资料。但最大的不一样之处在于Cookie是将数据存放在客户端的计算机之中,而Session则是将数据存放于服务器系统之下。Session的中文意思是会话,在Web系统中,一般是指用户与Web系统的对话过程。本文将详细介绍Session的内容php

 

Session ID

  在Web技术发展史上,虽然Cookie技术的出现是一个重大的变革,但Cookie是在客户端的计算机中保存资料,因此引发了一个争议。用户有权阻止Cookie的使用,使Web服务器没法经过Cookie来跟踪用户信息。而Session技术是将使用者相关的资料存放在服务器的系统之下,因此使用者没法中止Session的使用html

  Session在客户端仅须要保存由服务器为用户建立的一个Session标识符,称为Session ID,而在服务器端(文件或数据库或MemCache中)保存Session变量的值。Session ID是一个既不会重复,又不容易被找到规律的,由32位16进制数组成的字符串mysql

  Session ID会保存在客户端的Cookie中,若是用户阻止Cookie的使用,则能够将Session ID保存在用户浏览器地址栏的URL中。当用户请求Web服务器时,就会把Session ID发送给服务器,再经过Session ID提取保存在服务器中的Session变量。能够把Session中保存的变量,当作是这个用户的全局变量,同一个用户对每一个脚本的访问都共享这些变量web

  当某个用户向Web服务器发出请求时,服务器首先会检查这个客户端的请求里是否已经包含了一个Session ID。若是包含,说明以前已经为此用户建立过Session,服务器则按该Session ID把Session检索出来使用。若是客户端请求不包含Session ID,则为该用户建立一个Session,而且生成一个与此Session相关联的Session ID,在本次响应中被传送给客户端保存sql

【session_start()】数据库

  用户向Web服务器发出请求时,必须首先使用session_start()函数来启动新会话或者重用现有会话,成功开始会话返回TRUE,反之返回FALSE数组

bool session_start ([ array $options = [] ] )

  由于基于Cookie的Session是在开启的时候,调用session_start()函数会生成一个惟一的SessionID,须要保存在客户端电脑的Cookie中,和setCookie()函数同样,调用以前不能有任何的输出,空格或空行也不行浏览器

  若是已经开启过Session,再次调用Session_start()函数时,不会再建立个新的Session ID。由于当用户再次访问服务器时,该函数会经过从客户端携带过来的Session ID,返回已经存在的Session。因此在会话期间,同一个用户在访问服务器上任何一个页面时,都是使用同一个 Session ID缓存

session_start();

  并且,使用session_start()方法会在服务器端创建一个同名的Session文件(文本文件)安全

  若是不想在每一个脚本都使用Session_start()函数来开启Session,能够在php.ini里设置"session.auto_start=1",则无须每次使用Session以前都要调用session_start()函数。但启用该选项也有一些限制,则不能将对象放入Session中,由于类定义必须在启动Session以前加载。因此不建议使用php.ini中的session.auto_start属性来开启Session

 

读写session

  使用session_start()方法启动session会话后,要经过访问$_SESSION数组来读写session。和$_POST、$_GET、$_COOKIE相似,$_SESSION也是超全局数组

  使用$_SESSION数组将数据存入同名Session文件中

<?php
session_start();
$_SESSION['username'] = 'huochai';
$_SESSION['age'] = 28;
?>

  同名Session文件能够直接使用文本编辑器打开,该文件的内容结构以下所示:

变量名|类型:长度:值;

<?php
session_start();
print_r ($_SESSION);//Array ( [username] => huochai [age] => 28 )
?>

  Session变量会被保存在服务器端的某个文件中,该文件的位置是经过php.ini文件,在session.save_path属性指定的目录下

 

配置Session

  在PHP配置文件php.ini中,有一组和Session相关的配置选项。经过对一些选项从新设置新值,就能够对Session进行配置,不然使用默认的Session配置

phpinfo();
复制代码
session.auto_start=0;在请求启动时初始化session
session.cache_expire=180;设置缓存中的会话文档在n分钟后过期
session.cookie_lifetime=0;设置cookie保存时间(s),至关于设置Session过时时间,为0时表示直到浏览器被重启
session.cookie_path=/;cookie的有效路径
session.cookie_domain=;cookie的有效域
session.name=PHPSESSID;用在cookie里的session的名字
session.save_handler=files;用于保存/取回数据的控制方式
session.save_path=/tmp;在save_handler设为文件时传给控制器的参数,这是数据文件将保存的路径.
session.use_cookies=1;是否使用cookies
复制代码

 

销毁Session

  当使用完一个Session变量后,能够将其删除,当完成一个会话后,也能够将其销毁。若是用户想退出Web系统,就须要提供一个注销的功能,把全部信息在服务器中销毁。销毁和当前Session有关的全部的资料,能够调用session_destroy()函数结束当前的会话,并清空会话中的全部资源

【session_destroy()】

bool session_destroy ( void )    

  session_destroy()销毁当前会话中的所有数据,删除同名Session文件,可是不会重置当前会话所关联的全局变量,也不会重置会话cookie。若是须要再次使用会话变量,必须从新调用session_start()函数

<?php
session_start();
session_destroy();
?>

  可使用unset()函数来释放在Session中注册的单个变量

print_r ($_SESSION);//'Array ( [username] => huochai [age] => 28 )'
unset($_SESSION['username']);
unset($_SESSION['age']);
print_r ($_SESSION);//'Array()'

  [注意]不要使用unset($_SESSION)删除整个$_SESSION数组,这样将不能再经过$_SESSION超全局数组注册变量了

  若是想把某个用户在Session中注册的全部变量都删除,能够直接将数组变量$_SESSION赋值为一个空数组

$_SESSION=array();    

  PHP默认的Session是基于Cookie的,Session ID被服务器存储在客户端的Cookie中,因此在注销Session时也须要清除Cookie中保存的SessionID,而这就必须借助setCookie()函数完成。在Cookie中,保存Session ID的Cookie标识名称就是Session的名称,这个名称是在php.ini中,经过session.name属性指定的值。在PHP脚本中,能够经过调用session_name()函数获取Session名称。删除保存在客户端Cookie中的Session ID

if(isset($_COOKIE[session_name()])) {
    setCookie(session_name(),'',time()-3600);
}

  经过前面的介绍能够总结出来,Session的注销过程共须要四个步骤

复制代码
<?php
//第一步:开启Session并初始化
session_start();

//第二步:删除全部Session的变量,也可用unset($_SESSION[xxx])逐个删除
$_SESSION = array();

//第三步:若是使用基于Cookie的Session,使用setCooike()删除包含Session Id的Cookie
if (isset($_COOKIE[session_name()])) {
    setcookie(session_name(),'', time()-42000);
}

//第四步:最后完全销毁Session,删除服务器端保留session信息的文件
session_destroy();
?>
复制代码

 

自动回收

  若是没有经过上述步骤销毁Session,而是直接关闭浏览器,或断网等状况,在服务器端保存的Session文件是不会被删除的。由于在php.ini配置文件中,默认的session.cookie_lifetime=0,表示Session ID在客户端Cookie的有效期限为直到关闭浏览器。Session ID消失了,但服务器端保存的Session文件并无被删除。因此,没有被Session ID关联的服务器端Session文件成为了垃圾,而系统则提供了自动清理的机制

  服务器保存的Session文件是普通文本文件,都有文件修改时间。经过在php.ini配置文件中设置session.gc_maxlifetime选项来设置一个到期时间(默认为1440秒,即24分钟)。垃圾回收程序在全部Session文件中排查出大于24分钟的文件。若是用户还在使用该文件,那么这个Session文件的修改时间就会被更新,将不会被排查到

  排除出来后,并不会马上清理垃圾,而是根据配置文件php.info中session.gc_probability/session.gc_divisor这两个值的比例来决定什么时候清理,默认值是1/100。表示排查100次,才有一次可能会启动垃圾回收机制,来自动回收垃圾。固然,这个值是能够修改的,但仍是要兼顾服务器的运行性能和存储空间

 

传递session

  使用Session跟踪一个用户,是经过在各个页面之间传递惟一的Session ID,并经过Session ID提取这个用户在服务器中保存的Session变量。常见的Session ID传送方法有如下两种

  一、基于Cookie的方式传递Session ID。这种方法更优化,但因为不老是可用,由于用户在客户端能够屏蔽Cookie

  二、经过URL参数进行传递,直接将会话ID嵌入到URL中去

  在Session的实现中一般都是采用基于Cookie的方式,客户端保存的Session ID就是一个Cookie。当客户禁用Cookie时,Session ID就不能再在Cookie中保存,也就不能在页面之间传递,此时Session失效。不过PHP5在Linux平台能够自动检查Cookie状态,若是客户端将它禁用,则系统自动把Session ID附加到URL上传送。而使用Windows系统做为Web服务器则无此功能

【经过Cookie传递Session ID】

  若是客户端没有禁用Cookie,则在PHP脚本中经过session_start()函数进行初始化后,服务器会自动发送HTTP标头将Session ID保存到客户端电脑的Cookie中
相似于下面的设置方式

//虚拟向Cookie中设置Session ID的过程
setCookie(session_name(),session_id(),0,'/')

  第一个参数中调用session_name()函数,返回当前Session的名称做为Cookie的标识名称。Session名称的默认值为PHPSESSID,是在php.ini文件中由session.name选项指定的值。也能够在调用session_name()函数时提供参数改变当前Session的名称

echo session_name();//PHPSESSID

  第二个参数中调用session_id()函数,返回当前Session ID做为Cookie的值。也能够经过调用session_id()函数时提供参数设定当前Session ID

echo session_id();//kstvdmae177qqk6jgvg6td12l1

  第三个参数的值0,是经过在php.ini文件中由session.cookiejifetime选项设置的值。默认值为0,表示SessIon ID将在客户机的Cookie中延续到浏览器关闭

  最后一个参数'/',也是经过PHP配置文件指定的值,在php.ini中由session.cookie.path选项设置的值。默认值为'/',表示在Cookie中要设置的路径在整个域内都有效

  若是服务器成功将Session ID保存在客户端的Cookie中,当用户再次请求服务器时,就会把Session ID发送回来。因此当在脚本中再次使用session_start()函数时,就会根据Cookie中的Session ID返回已经存在的Session

【经过URL传递Session ID】

  若是客户浏览器支持Cookie,就把Session ID做为Cookie保存在浏览器中。但若是客户端禁止Cookie的使用,浏览器中就不存在做为Cookie的Session ID,所以在客户请求中不包含Cookie信息。若是调用session_start()函数时,没法从客户端浏览器中取得做为Cookie的Session ID,则又建立了一个新的Session ID,也就没法跟踪客户状态。所以,每次客户请求支持Session的PHP脚本,session_start()函数在开启Session时都会建立一个新的Session,这样就失去了跟踪用户状态的功能

  若是客户浏览器不支持Cookie,PHP则能够重写客户请求的URL,把Session ID添加到URL信息中。能够手动地在每一个超连接的URL中都添加一个Session ID,但工做量比较大,不建议使用这种方式。以下所示:

<?php
    session_start();
    echo '<a href="demo.php?'.session_name().'='.session_id() .'">连接演示</a>';
?>

  在使用Linux系统作服务器时,而且选用PHP4.2之后的版本,则在编辑PHP时若是使用了-enable-trans-sid配置选项,和运行时选项session.use_trans_sid都被激活,在客户端禁用Cookie时,相对URL将被自动修改成包含会话ID。若是没有这么配置,或者使用Windows系统做为服务器时,可使用常量SID。该常量在会话启动时被定义,若是客户端没有发送适当的会话Cookie,则SID的格式为session_name=session_id,不然就为一个空字符串。所以能够无条件地将其嵌入到URL中去。以下所示

//当阻止cookie时,SID返回'PHPSESSID=p2qouo8hjarul0a0ii5jmocmc0',不然返回一个空字符串
echo SID;
复制代码
<?php
    session_start();
    $_SESSION["usemame"]="admin";
    echo "Session ID:".session_id()."<br>";
?>
<a href="test2.php?<?php echo SID ?>">经过URL传递Session ID</a>
复制代码

  若是使用Linux系统做为服务器,并配置好相应的选项,就不用手动在每一个URL后面附加SID,相对URL将被自动修改成包含Session ID。但要注意,非相对的URL被假定为指向外部站点,所以不能附加SID。由于这多是个安全隐患,会将SID泄露给不一样的服务器

 

自定义Session

  在系统中使用Session技术跟踪用户时,Session默认的处理方式是使用Web服务器中的文件来记录每一个用户的会话信息,经过php.ini中的session_save_path建立会话数据文件的路径。这种默认的处理方式虽然很方便,但也有一些缺陷。例如,登陆用户若是很是大,文件操做的I/O开销就会很大,会严重影响系统的执行效率。另外,最主要的是自己的session机制不能跨机,由于对于访问量比较大的系统,一般都是采用多台web服务器进行并发处理,若是每台web服务器都各自独立地处理Session,就不可能达到跟踪用户的目的。这时就须要改变session的处理方式,常见的跨机方法就是经过自定义session的存储方式,能够将session信息使用NFS或SAMBA等共享技术保存到其余服务器中,或使用数据库来保存session信息,最优的方式是使用memcached来进行session存储

  不管是用memcached、数据库、仍是经过NFS或SAMBA共享session信息,其原理是同样的,都是经过PHP中的session_set_save_handler()函数来改变默认的处理方式,指定回调函数来自定义处理

Session_set_save_hander(callback open,callback close,call read,callback write,callback destro,callback gc);

  该函数共须要6个回调函数做为必选参数,分别表明了Session生命周期中的6个过程,用户经过自定义每一个函数,来设置Session生命周期中每一个环节的信息处理

  回调函数的执行时机以下所示

复制代码
回调函数        描述 
open          运行session_start()时执行,该函数须要声明两个参数,系统自动将php.ini中的session_save_path选项值传递给该函数的第一个参数,将Session名自动传递给第二个参数中,返回true则能够继续向下执行
close         该函数不须要参数,在脚本执行完成或调用session_write_close()、session_destroy()时被执行,即在全部session操做完成后被执行。若是不须要处理,则直接返回true便可 
read          在运行session_start()时执行,由于在开启会话时,会read当前session数据并写入$_SESSION变量。须要声明一个参数,系统会自动将Session ID传递给该函数,用于经过Session ID获取对应的用户数据,返回当前用户的会话信息写入$_SESSION变量
write         该函数在脚本结束和对$_SESSION变量赋值数据时执行。须要声明两个参数,分别是Session ID和串行化后Session信息字符串。在对$_SESSION变量赋值时,就能够经过Session ID找到存储的位置,并将信息写入。存储成功能够返回true继续向下执行
destroy       在运行session_destroy()时执行,须要声明一个参数,系统会自动将Session ID传递给该函数,去删除对应的会话信息
gc            垃圾回收程序启动时执行。须要声明一个参数,系统自动将php.ini中的session_gc_maxlifetime选项值传给该函数,用于删除超过这个时间的Session信息,返回true则能够继续向下执行
复制代码

  在运行session_start()时分别执行了open(启动会话)、read(读取session数据至$_SESSION)和gc(清理垃圾),脚本中全部对$_SESSION的操做均不会调用这些回调函数。在调用session_destroy()函数时,执行destroy销毁当前session(通常是删除相应的记录或文件),但此回调函数销毁的只是Session的数据,此时若是输出$_SESSION变量,仍然有值,但此值不会再close后被写回去。在调用session_write_close()函数时执行write和close,保存$_SESSION至存储,若是不手工使用此方法,则会在脚本结束时被自动执行

  [注意]session_set_save_hander()函数必须在php.ini中设置session_save_hander选项的值为”user”时(用户自定义处理器),才会被系统调用

复制代码
<?php
    $sess_save_path ="";
    function open($save_path,$session_name){
        global $sess_save_path; 
        $sess_save_path = $save_path;
        return true; 
    }  
    function close(){
        return true; 
    }
    function read($id){
        global $sess_save_path;  
        $sess_file ="{$sess_save_path}/sess_{$id}"; 
        return (string) @file_get_contents($sess_file); 
    }
    function write($id,$sess_data){
        global $sess_save_path;  
        $sess_file ="{$sess_save_path}/sess_{$id}"; 
        if($fp=@fopen($sess_file,"w")){   
            $return = fwrite($fp,$sess_data);
            fclose($fp); 
            return $return; 
        }else{  
            return false; 
        } 
    }  
    function destroy($id){ 
        global $sess_save_path;  
        $sess_file ="{$sess_save_path}/sess_{$id}"; 
        return (@unlink($sess_file)); 
    }   
    function gc($maxlifetime){  
        global $sess_save_path;     
        foreach(glob("{$sess_save_path}/sess_*") as $filename){ 
            if(filemtime($filename) + $maxlifetime <time() ){ 
                @unlink($filename); 
            } 
        }   
        return true; 
    } 
    session_set_save_hander(“open","close","read","write","destroy","gc");
    session_start();
?>
复制代码

 

数据库处理

  若是网站访问量很是大,须要采用负载均衡技术搭载多台Web服务器协同工做,就须要进行Session同步处理。使用数据库处理Session会比使用NFS及SAMBA更占优点,能够专门创建一个数据库服务器存放Web服务器的Session信息,当用户无论访问集群中的哪一个Web服务器,都会去这个专门的数据库,访问本身在服务器端保存的Session信息,以达到Session同步的目的。另外,使用数据库处理Session还能够给咱们带来不少好处,好比统计在线人数等。若是mysql也作了集群,每一个mysql节点都要有这张表,而且这张Session表的数据要实时同步

  在使用默认的文件方式处理Session时,有3个比较重要的属性,分别是文件名称、文件内容及文件的修改时间:经过文件名称中包含的Session ID,用户能够找到本身在服务器端的Session文件;经过文件内容用户能够在各个脚本中存取$_session变量;经过文件的修改时间则能够清除全部过时的Session文件。因此使用数据表处理Session信息,也最少要有这三个字段(Session ID、修改时间、Session内容信息),固然若是考虑更多的状况,例如,用户改变了IP地址,用户切换了浏览器等,还能够再自定义一些其余字段。下面为Session设计的数据表结构包含5个字段,建立保存Session信息表session的SQL语句以下所示:

复制代码
CREATE TABLE session(
    sid CHAR(32) NOT NULL DEFAULT '',
    update INT NOT NULL DEFAULT 0,
    client_ip CHAR(15) NOT NULL DEFAULT '',
    user_agent CHAR(200) NOT NULL DEFAULT '',
    data TEXT,
    PRIMARY KEY(sid)
);
复制代码

  数据表session建立成功后,再经过自定义的处理方式,将Session信息写入到数据库中

复制代码
<?php
class DBSession {
    public static $pdo;             //pdo的对象
    public static $ctime;           //当前时间
    public static $maxlifetime;     //最大的生存时间
    public static $uip;             //用户正在用的ip
    public static $uagent;          //用户正在用的浏览器

    //开启和初使化使用的, 参数须要一个路
    public static function start(PDO $pdo) {
        
        self::$pdo = $pdo;
        self::$ctime = time();
        self::$maxlifetime = ini_get("session.gc_maxlifetime");
        self::$uip = !empty($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : (!empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : (!empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : "") );

        filter_var(self::$uip, FILTER_VALIDATE_IP) && self::$uip = '';
        self::$uagent = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : "" ;

        //注册过程, 让PHP本身处理session时,找这个函数指定的几个周期来完成
        session_set_save_handler(
            array(__CLASS__, "open"), 
            array(__CLASS__,"close"),
            array(__CLASS__, "read"), 
            array(__CLASS__, "write"),
            array(__CLASS__, "destroy"), 
            array(__CLASS__,"gc"));
        session_start();  //开启会话
    }

    // 开启时, session_start()
    public static function open($path, $name) {
        return true;
    }

    //关闭
    public static  function close() {
        return true;
    }

    //读取 echo $_SESSION['username'] 
    public static  function read($sid) {
        $sql = "select * from session where sid = ?";
        $stmt = self::$pdo -> prepare($sql);
        $stmt -> execute(array($sid));
        $result = $stmt -> fetch(PDO::FETCH_ASSOC);
        //若是尚未会话信息,返回空字符串
        if(!$result) {
            return '';
        }
        //若是超出时间,销毁session
        if($result['utime'] + self::$maxlifetime < self::$ctime) {
            self::destroy($sid);
            return '';
        }
        //若是用户换了ip或换了浏览器
        if($result['uip'] != self::$uip || $result['uagent'] != self::$uagent) {
            self::destroy($sid);
            return '';
        }
        return $result['sdata'];

    }

    //写入 $_SESSION['username'] = "meizi";
    public static  function write($sid, $data) {

        //经过sid获取已经有的数据
        $sql = "select * from session where sid = ?";
        $stmt = self::$pdo->prepare($sql);
        $stmt -> execute(array($sid));
        $result = $stmt -> fetch(PDO::FETCH_ASSOC);
        
        //若是已经获取到了数据,就不插入而更新
        if($result) {
            //若是数据和原来的不一样才更新
            if($result['sdata'] != $data || $result['utime']+10 < self::$ctime) {
                $sql = "update session set sdata = ?, utime = ? where sid=?";
                $stmt = self::$pdo->prepare($sql);
                $stmt -> execute(array($data, self::$ctime, $sid));
            }

        //若是没有数据,就新插入一条数据
        } else {
        
            if(!empty($data)) {
                $sql = "insert into session(sid, sdata, utime, uip, uagent) values(?, ?, ?, ?, ?)";
                $stmt = self::$pdo -> prepare($sql);
                $stmt -> execute(array($sid, $data, self::$ctime, self::$uip, self::$uagent));
            }
        }

    }

    //销毁 session_destroy() 
    public static  function destroy($sid) {
        $sql = "delete from session where sid=?";
        $stmt = self::$pdo->prepare($sql);
        return $stmt -> execute(array($sid)); 
    }

    //回收垃圾
    public static  function gc($maxlifetime) {
        //    utime < ctime - self::$maxlifetime
        $sql = "delete from session where utime < ?";
        $stmt = self::$pdo->prepare($sql);
        return $stmt -> execute(array(self::$ctime - self::$maxlifetime));     
    }
}
    //开启
    DBSession::start($pdo);
复制代码

 

memcached处理

  用数据库来同步Session会加大数据库的负担,由于数据库原本就是容易产生瓶颈的地方,但若是采用MemCache来处理Session是很是合适的,由于MemCache的缓存机制和Session很是类似。另外,MemCach能够作分布式,可以把Web服务器中的内存组合起来,成为一个”内存池”,不论是哪一个服务器产生的Session,均可以放到这个“内存池”中,其余的Web服务器均可以使用。以这种方式来同步Session,不会加大数据库的负担,而且安全性也要比使用Cookie高。把session放到内存里面,读取也要比其余处理方式快不少

  自定义使用memcached处理session信息,和自定义数据库的处理方式相同,但要简单得多,由于MemCache的工做机制和Session技术很类似

复制代码
<?php

class MemSession {
    public static $mem;             //pdo的对象
    public static $maxlifetime;     //最大的生存时间

    public static function start(Memcache $mem) {    
        self::$mem = $mem;    
        self::$maxlifetime = ini_get("session.gc_maxlifetime");
    
        //注册过程, 让PHP本身处理session时,按照这个函数指定的几个周期来完成
        session_set_save_handler(
            array(__CLASS__, "open"), 
            array(__CLASS__,"close"),
            array(__CLASS__, "read"), 
            array(__CLASS__, "write"),
            array(__CLASS__, "destroy"), 
            array(__CLASS__,"gc"));
        session_start();  //开启会话
    }

    // 开启时,session_start()
    public static function open($path, $name) {
        return true;
    }

    //关闭
    public static  function close() {
        return true;
    }

    //读取 echo $_SESSION['username'] 
    public static  function read($sid) {
        $data = self::$mem -> get($sid);
        if(empty($data)) {
            return '';
        }
        return $data;
    }

    //写入
    public static  function write($sid, $data) {
        self::$mem -> set($sid, $data, MEMCACHE_COMPRESSED, self::$maxlifetime);
    }

    //销毁 session_destroy() 
    public static  function destroy($sid) {
        self::$mem -> delete($sid, 0);

    }

    //回收垃圾
    public static  function gc($maxlifetime) {
        return true;    
    }
}
    //建立对象
    $mem = new Memcache();
    //添加两台memcache服务器
    $mem -> addServer("localhost", 11211);
    $mem -> addServer("192.168.1.3", 11211);
    //开启
    MemSession::start($mem);
?>
复制代码
相关文章
相关标签/搜索