Swift51.com
麦子学院 头像
麦子学院  2017-06-03 22:49

Php学习之session机制详解

回复:0  查看:2355  

本文和大家分享的主要是php中session机制相关内容,一起来看看吧,希望对大家学习php有所帮助。

  默认情况下,我们是直接使用SESSION来操作会话,并且以文件的形式保存,一个会话对应一个文件。如果单个目录下存储太多会话文件影响读取效率,可以通过配置多级目录存储。默认使用文件保存会话,存在单机情况,不能部署应用群集的方式来扩展PHP应用。但是使用memcacheredis等扩展,通过配置可以直接把会话保存到memcacheredis中,并且不需要改变之前的使用方式,直接使用SESSION来操作会话,并且以文件的形式保存,一个会话对应一个文件。如果单个目录下存储太多会话文件影响读取效率,可以通过配置多级目录存储。默认使用文件保存会话,存在单机情况,不能部署应用群集的方式来扩展PHP应用。但是使用memcacheredis等扩展,通过配置可以直接把会话保存到memcacheredis中,并且不需要改变之前的使用方式,直接使用_SESSION,这样能方便地扩展集群,并且简单高效。

  PHP Session的启动,可以配置为是否自动启动,是的话,每个请求一开始,就可以直接使用SESSION了,SESSION了,_SESSION里的内容已经(从文件 、memcacheredis中)取出来了;如果否,程序中则要调用session_start来启动。想要更多的控制权,就不要自动启动,比如一些页面不需要会话的,就不应启动会话(因为启动了又不用,还要浪费会话读取的功夫)。

  进一步探究,PHP提供了一套机制:session_set_save_handler注册回调方法和实现SessionHandlerInterface接口(5.4版本后支持),这两者使用差别不是很多,随意选择,都要实现open, read, close,write,gc,destroy这几个方法。当session_start()时,调用openread方法,把会话读取到SESSION变量中,用户就可以在当前请求中,存取SESSION变量中,用户就可以在当前请求中,存取_SESSION变量。在程序执行完后,在输出流结束以后,在有 register_shutdown_function() 方法执行以后,执行writeclose方法,将会话内容写回到存储系统。这样我们就可以自定义把会话保存到数据库中,或者保存到memcache/redis等缓存系统中。

  根据上面PHP会话机制的了解,有如下主要实践,也是优化方案:

  1. 把会放的启动控制放到控制器(基类控制器、子类控制器、甚至控制器中的方法),让控制器决定是否使用会话。

  2. 不要直接使用SESSION变量,而是封成方法,比如sget/sset/sdel来获取/保存/删除会话内容,因为直接使用SESSION变量,而是封成方法,比如sget/sset/sdel来获取/保存/删除会话内容,因为直接使用_SESSION无法进一步控制或优化。

  3. 实际上网站在使用会话时,大部分都是读取操作,而不会修改会话内容,因此可采取只读而不回写策略,能减少一次网络操作。需要结合第2点,当会话操作时,维护一个变量isChange,读会话时不需要设置isChange,读会话时不需要设置isChange,设置或删除会话时isChange=true;当PHP执行session方法write时,对isChange=true;当PHP执行session方法write时,对isChange进行判断,有变更时进行写回,没有变更时,直接返回。

  进一步的考虑是,把session的内容保存到cookie中,并进行加密。这样的好处是,不需要为session消耗太多服务器资源,坏处是,增加稍许的网络流量,总得来说值得使用。cookie尽量不要保存太多数据,可结合数据库或缓存系统,比如只把登录所需要的用户角色权限相关数据作为会话保存到cookie中,而与购物车,其它临时数据等存到缓存。

  session数据的编码解码,简单地可使用serialize/unserialize/json_encode/json_decode进行编码解码。而加解密按需选取一个加密算法即可。

  使用cookie会话一般都要 ob_start()开始输出缓冲区, 注意不要在在关闭缓冲区或输出流关闭后再设置cookie,或者输出内容后再设置 cookie, 否则会报: Cannot modify header information - headers already sent 。如果是在程序结束后,再调用sessionwrite方法设置cookie,在遇到输出图形校验码或比较大的文件内容等情况会出错。一种解决方法在设置会话时立即输出header,然后再输出其它内容,而不是等到执行会话的write方法时再输出cookieheader信息。

  如果把session放到cookie中,会增大header头部数据量,通过nginx等反向代理转发时,可能需要调整转发的buffer.

 

来源:CSDN