这两天遇到了一个很奇怪的问题,更新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. Node.js学习笔记(一)基础介绍

    什么是Node.js 官网介绍: Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js us ...

  2. BZOJ 3527: [Zjoi2014]力(FFT)

    我们看一下这个函数,很容易就把他化为 E=sigma(aj/(i-j)/(i-j))(i>j)-sigma(aj/(i-j)/(i-j))(j>i) 把它拆成两半,可以发现分子与分母下标相 ...

  3. 对本地Solr服务器添加IK中文分词器实现全文检索功能

    在上一篇随笔中我们提到schema.xml中<field/>元素标签的配置,该标签中有四个属性,分别是name.type.indexed与stored,这篇随笔将讲述通过设置type属性的 ...

  4. 第十八篇 js高级知识---作用域链

    一直有想法去写写js方面的东西,我个人是最喜欢js这门语言,喜欢的他的自由和强大,虽然作为脚本语言有很多限制的地方,但也不失为一个好的语言,尤其是在H5出现之后.下面开始说说js的方面的东西,由于自己 ...

  5. nodejs中的路由

    一.路由初步 url.parse(string).query | url.parse(string).pathname | | | | | ------ -------------------http ...

  6. SqlService性能检测和优化工具

    工具概要 如果你的数据库应用系统中,存在有大量表,视图,索引,触发器,函数,存储过程,sql语句等等,又性能低下,而苦逼的你又要对其优化,那么你该怎么办?哥教你,首先你要知道问题出在哪里?如果想知道问 ...

  7. jquery ajax标准写法

    $.ajax({ url:url,                      //地址 type:'post', //请求方式 还可以是get type不可写成Type 不让会导致数据发送不过去,使用 ...

  8. 讲一个使用jquery-slick旋转木马效果插件案例

    效果展示连接 http://www.jqcool.net/demo/201405/jquery-slick/ 今天刚接触这个插件,被这插件搞的大脑风暴了 所以来记录一下使用方法 首先注意一点 不特别标 ...

  9. JS判断手机当前的系统类型

    <script language="javascript"> window.onload = function () { var n = navigator.userA ...

  10. MyEclipse下安装MyBatis Generator代码反向生成工具

    一.离线方式: 在http://mybatis.googlecode.com/svn/sub-projects/generator/trunk/eclipse/UpdateSite/下载 featur ...