php的session扩展可以将session数据存入任意容器,只要容器实现了php_session.h中的接口:

  1. typedef struct ps_module_struct {
  2.     const char *s_name;
  3.     int (*s_open)(PS_OPEN_ARGS);
  4.     int (*s_close)(PS_CLOSE_ARGS);
  5.     int (*s_read)(PS_READ_ARGS);
  6.     int (*s_write)(PS_WRITE_ARGS);
  7.     int (*s_destroy)(PS_DESTROY_ARGS);
  8.     int (*s_gc)(PS_GC_ARGS);
  9.     char *(*s_create_sid)(PS_CREATE_SID_ARGS);
  10. } ps_module;

如果在php.ini中定义了session.auto_start = 1,session扩展在请求初始化阶段(rinit)会调用s_open并s_read数据。
如果在php页面中调用了session_start()(只有第一次调用生效),session扩展也会调用s_open并s_read数据。
但是对于一些涉及不到session数据的页面,如果也去读取session数据会造成性能上的浪费,如磁盘操作或网络操作。
所以要想个办法对涉及session数据和不涉及session数据的页面区别对待,但是处理代码需要是一致的。
想的办法就是去掉session.auto_start = 1改成session.auto_start = 0并对cookie中没有session_name的请求延迟调用session_start(),
如果cookie中没有session_name,调用session_start()时,session扩展会自动生成一个session_id并发送Set-Cookie头,头信息的输出要在页面输出内容前或者把页面内容放入输出缓冲延迟输出。
最终的实现方式如下:
auto_prepend_file:

  1. <?php
  2. if (isset($_COOKIE[session_name()])) {
  3.     define('SESSION_STARTED', true);
  4.     @session_start();
  5. } else {
  6.     ob_start();
  7. }

auto_append_file:

  1. <?php
  2. if (!defined('SESSION_STARTED') && $_SESSION) {
  3.     $session_copy = $_SESSION;
  4.     @session_start();
  5.     if (!$_SESSION) {
  6.         $_SESSION = $session_copy;
  7.     }
  8.     ob_end_flush();
  9. }



10-03 07:50