title: Laravel session gets suddenly destroyed
body: <p>I have a multi-page form that handles sport event registrations. We are getting a lot of users (about 15% of all users, platform/browser independent) that experience the following error:</p>
  
  <p>The form contains the following pages:</p>
  
  <ol>
  <li>Start</li>
  <li>Details</li>
  <li>Team</li>
  <li>Class</li>
  <li>Batch</li>
  <li>Merchandise</li>
  <li>Survey</li>
  <li>Complete</li>
  </ol>
  
  <p>On every page, we check if the session contains the data from the previous page. If not, we redirect him back.</p>
  
  <p>The issue that encounters is that the 15% group gets redirected back after inputting data on step 4.</p>
  
  <p>This probably means that the session/data gets corrupted in the store function from step 4, but I don't have any clue how/why/where. But if this is the issue, it doesn't make sense that only 15% of our users get the issue. Also, after hours of trying, we where not able to reproduce this error.</p>
  
  <p>I know the session gets completely flushed/destroyed because the users get cascaded back: showBatchPage reverts the user back to showClassPage, showClassPage to showMembersPage, showMembersPage to showStartPage etc. We also log these reverts.</p>
  
  <p>My code looks like the following:</p>
  
  <pre><code>&lt;?php
  
  public function saveClassPage($slug)
  {
      $rules = [];
      $messages = [];
      $memberClasses = [];    
  
      // prepare solo error messages    
      foreach (Session::get('entry.members') as $id =&gt; $member)
      {
          if (!isset($member['group'])) {
              $rules["class.{$id}"] = 'required';
              $messages["class.{$id}.required"] = "Please select a class for member {$member['firstname']} {$member['lastname']}";
          }
      }
  
      // prepare team error messages
      foreach (Session::get('entry.groups', []) as $id =&gt; $group)
      {
          $rules["group.{$id}"] = 'required';
          $messages["group.{$id}.required"] = "Please select a class for group {$group['name']}";
      }
  
      $validator = Validator::make(Input::all(), $rules, $messages);
  
      // loop trough solo members and set class
      foreach (Input::get('class', []) as $i =&gt; $class)
      {
          Session::put("entry.members.{$i}.class", $class);
  
          // if there is only one class in the batch, assign it
          $memberClasses[$i] = ClassModel::find($class);
          if ($memberClasses[$i]-&gt;batches()-&gt;count() &lt; 2) {
              Session::put("entry.members.{$i}.batch", $memberClasses[$i]-&gt;batches()-&gt;first()-&gt;id);
          }
      }
  
      // loop trough teams and set class
      foreach (Input::get('group', []) as $i =&gt; $class)
      {
          foreach (Session::get("entry.groups.{$i}.members", []) as $id)
          {
              Session::put("entry.members.{$id}.class", $class);
  
              // if there is only one class in the batch, assign it
              $memberClasses[$id] = ClassModel::find($class);
              if ($memberClasses[$id]-&gt;batches()-&gt;count() &lt; 2) {
                  Session::put("entry.members.{$i}.batch", $memberClasses[$id]-&gt;batches()-&gt;first()-&gt;id);
              }
          }
          Session::put("entry.groups.{$i}.class", $class);
      }
  
      $allClassesAreEmpty = true;
      foreach ($memberClasses as $class)
      {
          if ($class-&gt;batches()-&gt;count() &gt; 1) {
              $allClassesAreEmpty = false;
              break;
          }
      }
  
      if ($validator-&gt;passes()) {
          // skip batch page if there is only one batch
          if ($allClassesAreEmpty) {
              return Redirect::action('EventEntryController@showExtrasPage', array('slug' =&gt; $slug));
          } else {
              return Redirect::action('EventEntryController@showBatchPage', array('slug' =&gt; $slug));
          }
      }
  
      return Redirect::action('EventEntryController@showClassPage', array('slug' =&gt; $slug))-&gt;withErrors($validator);
  }
  
  public function showBatchPage($slug)
  {
      $firstMember = head( Session::get('entry.members', []) );
  
      if (!isset($firstMember['class'])) {
          Log::info('showBatchPage@revertToClass');
  
          return Redirect::action('EventEntryController@showClassPage', array('slug' =&gt; $slug));
      }
  
      // other stuff (preparing view data etc.)
  
      return View::make('entry/batch', $viewData);
  }
  </code></pre>
  
  <p>My app/config/session.php</p>
  
  <pre><code>&lt;?php
  
  return array(
  
      /*
      |--------------------------------------------------------------------------
      | Default Session Driver
      |--------------------------------------------------------------------------
      |
      | This option controls the default session "driver" that will be used on
      | requests. By default, we will use the lightweight native driver but
      | you may specify any of the other wonderful drivers provided here.
      |
      | Supported: "file", "cookie", "database", "apc",
      |            "memcached", "redis", "array"
      |
      */
  
      'driver' =&gt; 'file',
  
      /*
      |--------------------------------------------------------------------------
      | Session Lifetime
      |--------------------------------------------------------------------------
      |
      | Here you may specify the number of minutes that you wish the session
      | to be allowed to remain idle before it expires. If you want them
      | to immediately expire on the browser closing, set that option.
      |
      */
  
      'lifetime' =&gt; 120,
  
      'expire_on_close' =&gt; false,
  
      /*
      |--------------------------------------------------------------------------
      | Session File Location
      |--------------------------------------------------------------------------
      |
      | When using the native session driver, we need a location where session
      | files may be stored. A default has been set for you but a different
      | location may be specified. This is only needed for file sessions.
      |
      */
  
      'files' =&gt; storage_path().'/sessions',
  
      /*
      |--------------------------------------------------------------------------
      | Session Database Connection
      |--------------------------------------------------------------------------
      |
      | When using the "database" or "redis" session drivers, you may specify a
      | connection that should be used to manage these sessions. This should
      | correspond to a connection in your database configuration options.
      |
      */
  
      'connection' =&gt; null,
  
      /*
      |--------------------------------------------------------------------------
      | Session Database Table
      |--------------------------------------------------------------------------
      |
      | When using the "database" session driver, you may specify the table we
      | should use to manage the sessions. Of course, a sensible default is
      | provided for you; however, you are free to change this as needed.
      |
      */
  
      'table' =&gt; 'sessions',
  
      /*
      |--------------------------------------------------------------------------
      | Session Sweeping Lottery
      |--------------------------------------------------------------------------
      |
      | Some session drivers must manually sweep their storage location to get
      | rid of old sessions from storage. Here are the chances that it will
      | happen on a given request. By default, the odds are 2 out of 100.
      |
      */
  
      'lottery' =&gt; array(2, 100),
  
      /*
      |--------------------------------------------------------------------------
      | Session Cookie Name
      |--------------------------------------------------------------------------
      |
      | Here you may change the name of the cookie used to identify a session
      | instance by ID. The name specified here will get used every time a
      | new session cookie is created by the framework for every driver.
      |
      */
  
      'cookie' =&gt; 'laravel_session',
  
      /*
      |--------------------------------------------------------------------------
      | Session Cookie Path
      |--------------------------------------------------------------------------
      |
      | The session cookie path determines the path for which the cookie will
      | be regarded as available. Typically, this will be the root path of
      | your application but you are free to change this when necessary.
      |
      */
  
      'path' =&gt; '/',
  
      /*
      |--------------------------------------------------------------------------
      | Session Cookie Domain
      |--------------------------------------------------------------------------
      |
      | Here you may change the domain of the cookie used to identify a session
      | in your application. This will determine which domains the cookie is
      | available to in your application. A sensible default has been set.
      |
      */
  
      'domain' =&gt; null,
  
      /*
      |--------------------------------------------------------------------------
      | HTTPS Only Cookies
      |--------------------------------------------------------------------------
      |
      | By setting this option to true, session cookies will only be sent back
      | to the server if the browser has a HTTPS connection. This will keep
      | the cookie from being sent to you if it can not be done securely.
      |
      */
  
      'secure' =&gt; false,
  
  );
  </code></pre>