Laravel 5.0 ajax request to save session variable

10,532

Your controller code works. It probably has to do with how your routes or your ajax call.

routes.php

Route::post('background-imgs/disable','SessionVarController@backgroundImgsOff');
Route::post('background-imgs/enable','SessionVarController@backgroundImgsOn');

jQuery

  $("#on").on('click', function () {
      var that = this;
      $.ajax({
          type: "POST",
          url:'/background-imgs/enable'
      });
  });

  $("#off").on('click', function () {
      var that = this;
      $.ajax({
          type: "POST",
          url:'/background-imgs/disable'
      });
  });

You could normalize this a bit if you wanted and return a value so you can see what's happening.

routes.php

Route::post('background-imgs/{action}','SessionVarController@backgroundImages')
    ->where('action', '[enable]*[disable]*');

controller

class SessionVarController extends Controller {

public function backgroundImages($action = 'enable')
{
    if(!Request::ajax())
    {
        abort(404, 'Page not found.');
    }
    if ($action === 'enable'){
        Session::forget(['backgroundImgDisable']);
        return Response::json(['background' => 'enabled']); 
    }
    Session::put(['backgroundImgDisable' => true]);
    return Response::json(['background' => 'disabled']); 

}

Edit per updated question

You need to add the X-Requested-With header to your XMLHttpRequest.

Laravel uses Symfony to check if it is an ajax request.

public function isXmlHttpRequest()
{
    return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
}

You javascript code should look like this.

function enableBackgroundImages() {
  if (window.XMLHttpRequest) {
      // code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp = new XMLHttpRequest();
  } else {
      // code for IE6, IE5
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.open("GET","{{ action('TestController@backgroundImgsOn') }}",true);
  xmlhttp.setRequestHeader('X-Requested-With','XMLHttpRequest');
  xmlhttp.send();
}
function disableBackgroundImages() {
  if (window.XMLHttpRequest) {
      // code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp = new XMLHttpRequest();
  } else {
      // code for IE6, IE5
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.open("GET","{{ action('TestController@backgroundImgsOff') }}",true);
  xmlhttp.setRequestHeader('X-Requested-With','XMLHttpRequest');
  xmlhttp.send();
}

You might want to look into jQuery for this. It adds a bit of bulk to your JavaScript but it is much easier to deal with.

You could write your methods like this.

function enableBackgroundImages() {
        $.get("{{ action('SessionVarController@backgroundImgsOn') }}");
}
function disableBackgroundImages() {
        $.get("{{ action('SessionVarController@backgroundImgsOff') }}");
}
Share:
10,532
Logan Hasbrouck
Author by

Logan Hasbrouck

I am a junior-level developer who works for the local county government. My hobbies include anime, games, building websites and biking. In terms of online gaming, I am known as 'NemesisSlayer'.

Updated on September 09, 2022

Comments

  • Logan Hasbrouck
    Logan Hasbrouck over 1 year

    I am attempting to use an ajax request to save a session variable which is used to disable my site's background images. As of right now, it DOES work if I simply go to the route itself, however, if I run the function through an ajax request, it fails completely and does NOT save the value to session even if it shows it in the dd(Session::all()) right after.

    <?php namespace App\Http\Controllers;
    
    use App\Http\Controllers\Controller;
    use Session;
    use Request;
    use App;
    use Response;
    
    class SessionVarController extends Controller {
    
        public function backgroundImgsOff()
        {
            if(Request::ajax())
            {
                Session::put(['backgroundImgDisable' => true]);
                return Response::json(); 
            }
            else
            {
                App::abort(404, 'Page not found.');
            }
        }
    
        public function backgroundImgsOn()
        {
            if(Request::ajax())
            {
                Session::forget(['backgroundImgDisable']);
                return Response::json(); 
            }
            else
            {
                App::abort(404, 'Page not found.');
            }
        }
    
    }
    

    Does anyone know why this seems to refuse to actually save the session variable? I read somewhere that it may have to do with session states, however, I have been unsuccessful in locating so much as a hint to a solution.

    EDIT: here is my ajax (keep in mind this is my first attempt at ajax).

    function enableBackgroundImages() {
        if (window.XMLHttpRequest) {
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp = new XMLHttpRequest();
        } else {
            // code for IE6, IE5
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        xmlhttp.open("GET","{{ action('SessionVarController@backgroundImgsOn') }}",true);
        xmlhttp.send();
    }
    function disableBackgroundImages() {
        if (window.XMLHttpRequest) {
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp = new XMLHttpRequest();
        } else {
            // code for IE6, IE5
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        xmlhttp.open("GET","{{ action('SessionVarController@backgroundImgsOff') }}",true);
        xmlhttp.send();
    }
    

    Here are the buttons on the page:

    <div id="background-on-off" style="display:inline-block;">
        Background Images: 
        <a href="#" onClick="enableBackgroundImages();">
            On
        </a>
        / 
        <a href="#" onClick="disableBackgroundImages();location.reload();">
            Off
        </a>
    </div>
    

    Lastly, here are my routes:

    Route::get('background_images_on', 'SessionVarController@backgroundImgsOn');
    Route::get('background_images_off', 'SessionVarController@backgroundImgsOff');
    

    Thanks.

  • lesssugar
    lesssugar over 8 years
    That's a valid point. And actually, @Logan Hasbrouck, returning a direct JSON response to the view is the only way to go here. The reason for this is that the view does not "know" about the Session change which happened during the Ajax call. The change will be reflected after the next page load, though. Pass the images state to the view, do what you need in the Ajax callback, and the Session variable will stay in place for future requests.
  • Logan Hasbrouck
    Logan Hasbrouck over 8 years
    @lesssugar When the user clicks to disable background images, immediately after the ajax request is sent and received I automatically reload the page so that the changes would take effect. I will take a look at my routes. As of right now I have it set up as a get request.
  • Logan Hasbrouck
    Logan Hasbrouck over 8 years
    Still doesn't work. My guess is that I messed up somewhere with my ajax seeing as this is my first time trying ajax. I added my ajax code and the buttons that call the ajax functions.
  • Logan Hasbrouck
    Logan Hasbrouck over 8 years
    @whoacowboy xmlhttp.setRequestHeader('X-Requested-With','XMLHttpRequest'‌​); got it to work. I tried with your original post using jquery, however, it still didn't recognize it as an ajax request (and I will attempting ajax using jquery here soon). Thanks mate.
  • whoacowboy
    whoacowboy over 8 years
    @LoganHasbrouck Good luck with it.