这两天遇到了一个很奇怪的问题,更新sessionsession的值不变。经过一番追查,终于找到问题,并搞明白了原理。写这篇博客记录下。

框架版本

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,当你将redisid的值改成2时,在访问,发现返回的还是1,而且之后的访问也都是1。这里说明一下session使用的是redis

解决问题

看到这样神奇的结果,百思不得其解。于是打开Xdebug,开始调试。经过多次调试,发现在执行完

\Illuminate\Session\Middleware\StartSession这个Middleware后,session里面的值就变回1了,在之前都是2。然后想到会不会我们的MiddlewareStartSession之前执行造成的,将我们的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 遇到的坑的更多相关文章

  1. laravel用redis保存session遇到的坑,没报错,但redis-cli就是查不到

    laravel用redis保存session遇到的坑, 配置redis存储session流程是这样的 在.evn文件中把session驱动和连接改为了redis的 如下: SESSION_DRIVER ...

  2. laravel中遇到的坑

    已经遇到的坑和未来可能遇到的坑都将在这里写出来: 在资源控制器中创建新的方法后(如果资源控制器中的7个方法无法满足你的需求时,你就会创建新的方法),接下来就是创建路由,这个时候注意了,你必须要把路由放 ...

  3. Laravel Session() 失效的问题

    之前因为自己自定义了后台的路由,然后路由定义的乱七八糟的. 突然发现session失效了,记录一下,避免后者遇坑. 路由组统一通过web中间件或者存在于一个中间件中 protected $middle ...

  4. laravel session的几个特点

    1. 只要访问了网站,就会创建一个临时的session 2.用户登录后sessionid就会发生变化 3.在这期间,即使使用4g网络,ip地址会不断发生变化,只要cookie中包含了sessionid ...

  5. Laravel session的保存机制

    与$_SESSION不同Laraver中的session是在当次程序执行完毕时保存到文件或其他存储引擎中的,也就是说如果使用了die等强制结束程序的函数将不会自动保存session导致session失 ...

  6. laravel session使用 转自http://blog.csdn.net/angle_hearts/article/details/53923782

    use Symfony\Component\HttpFoundation\Session\Session;//存储session $session = new Session;$session-> ...

  7. laravel 容器注入的坑

    今天遍历添加数据时遇到个坑,哪位大神知道什么原因?? 起初的代码是这样的:(部分) public function addActive(Request $request, Activenorms $a ...

  8. 记录关于使用ADO.NET 连接池连接Oracle时Session信息不更新的坑

    最近的一个项目中,由于界面查询的数据量比较大,关联的表比较多,有些数据查出来需要临时保存起来供后面的查询使用,于是想到了用oracle的临时表来实现这个需求.大家都知道,oracle的临时表有两种:事 ...

  9. Laravel学习笔记之Session源码解析(下)

    说明:在中篇中学习了session的CRUD增删改查操作,本篇主要学习关闭session的相关源码.实际上,在Laravel5.3中关闭session主要包括两个过程:保存当前URL到session介 ...

随机推荐

  1. html5_canvas初学

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. [bzoj1070][SCOI2007]修车——费用流

    题目大意: 传送门 题解: 本题和(POJ3686)[http://poj.org/problem?id=3686]一题一模一样,而且还是数据缩小以后的弱化版QAQ,<挑战程序设计竞赛>一 ...

  3. 不惧面试:HTTP协议(3) - Cookie

    v博客前言 先交代下背景,写这个系列的原因是总结自己遇到的面试题以及可能遇到的题目,更重要的是,今年定的目标是掌握网络这一块的知识点,先是搞懂HTTP协议,然后是TCP/IP协议,再就是WCF如何运用 ...

  4. 电脑机器刷BIOS

    http://www.51nb.com/forum/viewthread.php?tid=934570&page=1#pid13765036 [原创]hp笔记本刷新bios失败后真的可以恢复吗 ...

  5. 利用Flume采集IIS日志到HDFS

    1.下载flume 1.7 到官网上下载 flume 1.7版本 2.配置flume配置文件 刚开始的想法是从IIS--->Flume-->Hdfs 但在采集的时候一直报错,无法直接连接到 ...

  6. logistic回归和probit回归预测公司被ST的概率(应用)

    1.适合阅读人群: 知道以下知识点:盒状图.假设检验.逻辑回归的理论.probit的理论.看过回归分析,了解AIC和BIC判别准则.能自己跑R语言程序 2.本文目的:用R语言演示一个相对完整的逻辑回归 ...

  7. C# 控制台倒计时

    年前经常聊天的大佬群里有人写了窗体的倒计时来计算下班时间和放假时间:) 简直就是在嘲讽我这种没有工作的人,哈哈哈 窗体的倒计时相当的没有技术含量,主要是不够炫酷,不能够体现我们程序员的身份. 那什么才 ...

  8. 移动OA日程支持费用及评论

    业务介绍 AIO7系统最新更新版本在移动OA的日程管理进行改进,增加了创建费用的功能,且在日程批注上也可查看:在日程个人界面和批注界面都支持了评论功能.移动OA上日程对费用及评论的支持,方便用户外出时 ...

  9. 配置虚拟主机(windows环境下nginx+php)

    需要给一个ip绑定不同域名,例如有两个项目/www/,/www2/ 需要http://a.com时访问的是www 项目 http://b.com访问的是www2项目   那么需要在nginx/conf ...

  10. 前端基本知识(四):JS的异步模式:1、回调函数;2、事件监听;3、观察者模式;4、promise对象

    JavaScript语言将任务的执行模式可以分成两种:同步(Synchronous)和异步(Asychronous). “同步模式”就是一个任务完成之后,后边跟着一个任务接着执行:程序的执行顺序和排列 ...