Nette对会话一直采取谨慎的态度。它只在用户需要的时候自动启动它们。这具体意味着。
- 当他们写到它时
- 当他们从它那里读取时,并且有一个会话ID cookie
因为如果cookie不存在,我们就不需要运行会话就知道里面没有数据了。所以不运行它,Nette可能会把购物车的内容返回为空,等等。
与自动启动相关的是会话启动过晚的问题,也就是在服务器已经发出输出,HTTP头信息不能再发送的时候。当会话启动时,会发送一个带有会话ID的cookie,以及头信息Pragma 和Expires 。为了尽量减少这个问题,Nette在设置为autoStart: smart(默认值)时,如果存在会话ID cookie,会在启动时自动启动会话。
然而,3.1.5版本解决了一些隐患。
数据访问
会话部分的数据通常以变量的形式被访问。
$section = $session->getSection('unique name');
$section->userName = 'john';
echo $section->userName;
然而,由于PHP的特殊技术限制,echo $section->userName 操作被检测为写。因此,即使上述的购物车读取$cart = $section->cart ,即使cookie不存在,也会启动一个会话。这就破坏了自动启动的效率。
这可以通过使用ArrayAccess语法来避免。
$section['userName'] = 'john';
echo $section['userName']; // it is a read operation
然而,ArrayAccess语法对用户来说可能太神奇了,有时并不像人们所期望的那样工作(例如,$section['cart'][] = $item 产生一个通知间接修改重载元素没有效果)。因此,在3.1和3.0系列的最新版本中,你会发现一组可理解的方法set(),get() 和remove() 来访问数据。过期时间也可以用set() 。
$section->set('flash', $message, '30 seconds');
因此,使用这些方法成为访问会话数据的首选方式。
存在Cookie时的自动启动
当会话ID变成无效时,即磁盘上没有相应的文件等,Nette会修改行为。Nette检测到这种情况,并生成一个新的ID和一个干净的文件,以防止攻击者可能的ID欺骗。现在,它反而删除了cookie,根本不创建文件。这样做的原因是为了避免在攻击者故意欺骗会话ID时在磁盘上创建空文件。
新的自动启动配置
选项autoStart 现在可以取新的值always 和never 。always 在启动后立即打开会话,与选项true 相同。一个新的选项是never ,它完全关闭自动启动,只有当你调用$session->start() ,才会打开会话。默认的变体仍然是smart ,如上所述,它不再在启动后打开会话,而是只在读或写的情况下打开。它实际上与false 完全相同。
v3.0系列将默认值从smart 改为false ,它也关闭了启动后的自动启动。
事件 onBeforeWrite
最后,Nette\Http\Session 对象现在有$onStart 和$onBeforeWrite 事件,所以你可以添加回调,在会话开始后或被写入磁盘然后终止前启动。
$session->onBeforeWrite[] = function () {
// zapíšeme data do session
$this->section->set('basket', $this->basket);
};
在测试新的行为时,请记住,Tracy在开发者模式下启动会话,因为它用它来显示Tracy Bar中的重定向条和AJAX请求。