Laravel Session 遇到的坑
这两天遇到了一个很奇怪的问题,更新session ,session的值不变。经过一番追查,终于找到问题,并搞明白了原理。写这篇博客记录下。
框架版本
Laravel 5.4
问题
先来描述下问题,我在我们项目基础的Middleware中,加入session操作,存入了一个值,再在Controller中取出使用,大致代码如下:
// Middleware
public function handle($request, Closure $next)
{
$id = Redis::get('id');
session(['id' => $id]);
return $next($request);
}
// Controller
public function index()
{
$id = session('id');
return ['id' => $id];
}
假设reids中的id是1,这一次访问index这个action,返回的是1,当你将redis中id的值改成2时,在访问,发现返回的还是1,而且之后的访问也都是1。这里说明一下session使用的是redis 。
解决问题
看到这样神奇的结果,百思不得其解。于是打开Xdebug,开始调试。经过多次调试,发现在执行完
\Illuminate\Session\Middleware\StartSession这个Middleware后,session里面的值就变回1了,在之前都是2。然后想到会不会我们的Middleware在StartSession之前执行造成的,将我们的Middleware移到StartSession之后,发现果然可以了,app/Http/Kernel.php中的代码如下:
protected $middlewareGroups = [
'web' => [
\Illuminate\Cookie\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\OurMiddleware::class,
]
];
其中的OurMiddleware是我们自己写的Middleware,之前是放在最上面的,$next($request)之前的代码的执行顺序是从上到下的,如果OurMiddleware中有些内容是必须在最开始的,可以考虑分成两个Middleware。
理解原理
虽然解决了问题,但还是不知道其原理究竟是怎样的,带着这样的疑问我继续查看源码,最终找到了相应的内容。
session不是实时落地的,也就是说当你调用session(['id' => $id])时,id并没有被真正存入redis中,而是缓存在\Illuminate\Session\Store单例的attributes属性中,可以查看其put方法,代码如下:
public function put($key, $value = null)
{
if (! is_array($key)) {
$key = [$key => $value];
}
foreach ($key as $arrayKey => $arrayValue) {
Arr::set($this->attributes, $arrayKey, $arrayValue);
}
}
```
\Illuminate\Session\Middleware\StartSession在执行时,回自动加载redis中已经实例化的数据,并覆盖\Illuminate\Session\Store单例中的attributes属性,所以这就导致我们一直取到的都是redis中的session数据。加载覆盖的代码如下:
protected function loadSession()
{
$this->attributes = array_merge($this->attributes, $this->readFromHandler());
}
protected function readFromHandler()
{
if ($data = $this->handler->read($this->getId())) {
$data = @unserialize($this->prepareForUnserialize($data));
if ($data !== false && ! is_null($data) && is_array($data)) {
return $data;
}
}
return [];
}
```
其中的readFromHandler方法就是获取redis中的session数据。
后记
其实这不是Laravel session的坑,是我自己踩坑,原谅我是个标题党
Laravel Session 遇到的坑的更多相关文章
- laravel用redis保存session遇到的坑,没报错,但redis-cli就是查不到
laravel用redis保存session遇到的坑, 配置redis存储session流程是这样的 在.evn文件中把session驱动和连接改为了redis的 如下: SESSION_DRIVER ...
- laravel中遇到的坑
已经遇到的坑和未来可能遇到的坑都将在这里写出来: 在资源控制器中创建新的方法后(如果资源控制器中的7个方法无法满足你的需求时,你就会创建新的方法),接下来就是创建路由,这个时候注意了,你必须要把路由放 ...
- Laravel Session() 失效的问题
之前因为自己自定义了后台的路由,然后路由定义的乱七八糟的. 突然发现session失效了,记录一下,避免后者遇坑. 路由组统一通过web中间件或者存在于一个中间件中 protected $middle ...
- laravel session的几个特点
1. 只要访问了网站,就会创建一个临时的session 2.用户登录后sessionid就会发生变化 3.在这期间,即使使用4g网络,ip地址会不断发生变化,只要cookie中包含了sessionid ...
- Laravel session的保存机制
与$_SESSION不同Laraver中的session是在当次程序执行完毕时保存到文件或其他存储引擎中的,也就是说如果使用了die等强制结束程序的函数将不会自动保存session导致session失 ...
- laravel session使用 转自http://blog.csdn.net/angle_hearts/article/details/53923782
use Symfony\Component\HttpFoundation\Session\Session;//存储session $session = new Session;$session-> ...
- laravel 容器注入的坑
今天遍历添加数据时遇到个坑,哪位大神知道什么原因?? 起初的代码是这样的:(部分) public function addActive(Request $request, Activenorms $a ...
- 记录关于使用ADO.NET 连接池连接Oracle时Session信息不更新的坑
最近的一个项目中,由于界面查询的数据量比较大,关联的表比较多,有些数据查出来需要临时保存起来供后面的查询使用,于是想到了用oracle的临时表来实现这个需求.大家都知道,oracle的临时表有两种:事 ...
- Laravel学习笔记之Session源码解析(下)
说明:在中篇中学习了session的CRUD增删改查操作,本篇主要学习关闭session的相关源码.实际上,在Laravel5.3中关闭session主要包括两个过程:保存当前URL到session介 ...
随机推荐
- php引入文件(include 和require的区别)
引入文件: 首先需要一个php文件: <?php class shao//类名必须和文件名相同!!! { public $xxx="666"; } $shili = new ...
- Raspberry树莓派学习笔记1—基本介绍
树莓派的简单介绍 一个名片大小的迷你个人电脑主机,还有wifi/蓝牙... 运行完整的Linux操作系统(注意关键字:完整,不是精简过的嵌入式Linux) 开源的硬件平台.与普通主机不同的是,它带有简 ...
- 数组&&函数数组
数组:一次性定义多个同类型的变量,数组在 内存中存储空间必须是连续的(查询比较快)定义数组: int a[]; int[] a;分配空间: a=new int[5]; 自动为数组元素赋以默认值 a[0 ...
- 普通用户创建ssh无密码访问
jenkins:120.145.120.76 ubuntu:kasumi msc1:10.25.164.100 ubuntu:kasumi 1.创建普通用户&修改密码: $useradd ub ...
- Transport (VMDB) error -44: Message
关于点击电源按钮的时候出现了这情况Transport (VMDB) error -44: Message. 虚拟机有个服务没开.开始菜单--运行--services.msc 回车 找到VMw ...
- vc release模式设置断点调试
在VC release模式做如下设置:在 工程->属性->c/c++->常规->调试信息格式选择 -> 程序数据库(/Zi) 在 工程->属性->链接器-&g ...
- ajax跨域问题及解决
overview ajax是一种创建交互式网页应用的网页开发技术,是一种用于创建快速动态网页的技术,通过在后台与服务器进行少量数据交换.而ajax的跨域问题则是请求了其他项目的接口地址,当协议.子域名 ...
- jeesite简单入口分析
这两天要开新项目 , 准备使用比较受欢迎的 jeesite框架 . jeesite是一个写好的网站 , 用到的框架比较多 具体请看 -- > github链接 下载下来之后 , 手动把maven ...
- 了解 : Odata 的 $filter
api/jobPosts?$filter=company/name eq "string" //基本 api/orders?$filter=orderItem/product/EF ...
- VUE2.0实现购物车和地址选配功能学习第一节(来源--慕课网河畔一角)
第一节 vue知识 vue-resource:和后台交互的一个插件,实现get.post和jsonp等功能.(替代jQuery) vue特点: 1.易用:通过创建vue实例,{{}}绑定数据十分方便 ...