默认情况下,PHP 的会话处理机制会设置会话 cookie 标头并存储会话,即使会话中没有数据也是如此。如果会话中没有设置数据,那么我不想要Set-Cookie
在响应中发送到客户端的标头,我不希望在服务器上存储空会话记录。如果数据添加到$_SESSION
,那么正常行为应该继续。
我的目标是实现 Drupal 7 和压力流 https://launchpad.net/pressflow除非将数据添加到其中,否则不会存储会话(或发送会话 cookie 标头)$_SESSION
应用程序执行期间的数组。此行为的目的是允许反向代理,例如Varnish http://varnish-cache.org/缓存和服务匿名流量,同时让经过身份验证的请求传递到 Apache/PHP。 Varnish(或另一个代理服务器)被配置为传递任何没有 cookie 的请求,正确地假设如果 cookie 存在,则该请求是针对特定客户端的。
我已经从 Pressflow 移植了使用的会话处理代码session_set_save_handler()
并覆盖执行session_write()
检查中的数据$_SESSION
保存之前将其保存为数组,并将其写为库,并在此处添加答案(如果这是最佳/唯一的路线)。
我的问题:虽然我可以实现完全自定义session_set_save_handler()
系统,是否有一种更简单的方法可以以相对通用的方式获得这种惰性会话创建行为,即透明的对于大多数应用程序?
好吧,一种选择是使用会话类来启动/停止/存储会话中的数据。所以,你可以这样做:
class Session implements ArrayAccess {
protected $closed = false;
protected $data = array();
protected $name = 'mySessionName';
protected $started = false;
protected function __construct() {
if (isset($_COOKIE[$this->name])) $this->start();
$this->data = $_SESSION;
}
public static function initialize() {
if (is_object($_SESSION)) return $_SESSION;
$_SESSION = new Session();
register_shutdown_function(array($_SESSION, 'close'));
return $_SESSION;
}
public function close() {
if ($this->closed) return false;
if (!$this->started) {
$_SESSION = array();
} else {
$_SESSION = $this->data;
}
session_write_close();
$this->started = false;
$this->closed = true;
}
public function offsetExists($offset) {
return isset($this->data[$offset]);
}
public function offsetGet($offset) {
if (!isset($this->data[$offset])) {
throw new OutOfBoundsException('Key does not exist');
}
return $this->data[$offset];
}
public function offsetSet($offset, $value) {
$this->set($offset, $value);
}
public function offsetUnset($offset) {
if (isset($this->data[$offset])) unset($this->data[$offset]);
}
public function set($key, $value) {
if (!$this->started) $this->start();
$this->data[$key] = $value;
}
public function start() {
session_name($this->name);
session_start();
$this->started = true;
}
}
在脚本调用开始时使用Session::initialize()
。它将用对象替换 $_SESSION ,并设置延迟加载。之后,你可以这样做
$_SESSION['user_id'] = 1;
如果会话未启动,它将启动,并且 user_id 键将设置为 1。如果在任何时候您想关闭(提交)会话,只需调用$_SESSION->close()
.
您可能想要添加一些更多的会话管理功能(例如 destroy、regenerate_id、更改会话名称的能力等),但这应该实现您想要的基本功能...
它不是一个 save_handler,它只是一个管理会话的类。如果你真的愿意,你可以在类中实现 ArrayAccess,并在构造时用该类替换 $_SESSION (这样做的好处是,遗留代码仍然可以像以前一样使用会话,而无需调用$session->setData()
)。唯一的缺点是我不确定 PHP 使用的序列化例程是否可以正常工作(您需要在某个时候将数组放回到 $_SESSION 中......可能使用register_shutdown_function()
...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)