SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 29
  1. #1
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question PHP Session won't update with AJAX

    I'm not sure if the problem can be solved by PHP or Javascript.

    I have an ajax call on my index.php page that is supposed to update a PHP session.
    Specifically the session stores the quantity of each product added to the session.

    This is the php file that is called by the AJAX script:
    ajax-api.php
    PHP Code:
    // AJAX passes variables:  q_code, q_qty, sess_id

    // make sure using same session id
    session_id($_GET['sess_id']);

    // the correct number is displayed, which means I am able to access the right session
    echo "alert('original quantity: ".$_SESSION['quote'][$_GET['q_code']]."')";

    $_SESSION['quote'][$_GET['q_code']]=$_GET['q_qty'];

    // this also shows the correct number
    echo "alert('final quantity: ".$_SESSION['quote'][$_GET['q_code']]."')"
    The problem is that it does not actually save to the PHP Session!

    As soon as I refresh the page or go to another page, that session variable is back to the original quantity.

    The session information is saved in a MySQL database. I do not know why the ajax script would return the correct quantity, but then subsequent pages show the wrong quantity.

    Any suggestions on whether PHP or JavaScript would fix this problem?


    Thanks!

  2. #2
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    you need to call session_start() before you can use a session. manually setting the session id via session_id() must come before starting the session.

  3. #3
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Still doesn't work!
    (Note I actually had called session_id and session_start in the above code. I actually called session_id twice accidentally, but even with the calls in the order below and no second call, it did not work)

    PHP Code:
    // AJAX passes variables:  q_code, q_qty, sess_id

    // make sure using same session id
    session_id($_GET['sess_id']);
    session_start();

    // the correct number is displayed! The correct session is accessed
    echo "alert('original quantity: ".$_SESSION['quote'][$_GET['q_code']]."')";

    $_SESSION['quote'][$_GET['q_code']]=$_GET['q_qty'];

    // this also shows the correct number after the session variable is set!
    echo "alert('final quantity: ".$_SESSION['quote'][$_GET['q_code']]."')"
    but it does not save!

  4. #4
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What happens when you directly goto that url in your browser, complete with query string args?

    clear your cookies.

  5. #5
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Unhappy

    After clearing cookies, I added two products to the quote. It showed 1 of each.
    Then I went to another page and back just to make sure (not using the back button but clicking a link)

    Then I pasted the ajax URL which showed the success message embedded in javascript for example: alert('quantities updated')

    I think it has to do with the http headers, since these are not sent or received in the ajax call (from what I understand).

    What drives me mad is that Live HTTP Headers in Firefox only shows the session ID, so the information should be stored in MySQL when the ajax is called, and still be there when I visit the next page!

  6. #6
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,015
    Mentioned
    62 Post(s)
    Tagged
    0 Thread(s)
    $_SESSION becomes locked and unchangeable once headers are sent to the browser. Headers will be sent when the first line of output is sent to the browser. So your problem here is your debug code that is echoing output before you apply your change

    On a related note, if you are using prototype.js framework you can make debugging AJAX much easier in firefox using the firebug console tool Using your script as an example

    PHP Code:
    // AJAX passes variables:  q_code, q_qty, sess_id

    /* Set our response header to javascript. Prototype.js will
     * eval our response out to the console (though any other
     * function can be called straight out of PHP with this 
     * technique
     */
    header ('Content-Type: application/javascript');

    /* Now we will start an output buffer to insure that we do
     * not output anything before we are ready to end our
     * script
     */
    @ob_start();

    // make sure using same session id
    session_id($_GET['sess_id']);
    session_start();

    // the correct number is displayed! The correct session is accessed
    echo "console.info('original quantity: ".$_SESSION['quote'][$_GET['q_code']]."')";

    $_SESSION['quote'][$_GET['q_code']]=$_GET['q_qty'];

    // this also shows the correct number after the session variable is set!
    echo "console.info('final quantity: ".$_SESSION['quote'][$_GET['q_code']]."')"

    /* Now that we're done we close the session formally */
    session_commit();

    /* And return our results as a javascript
     * prototype will auto eval the response
     * and populate the firebug console.
     */
    $output = @ob_get_clean();
    echo 
    $output

  7. #7
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Michael Morris View Post
    $_SESSION becomes locked and unchangeable once headers are sent to the browser. Headers will be sent when the first line of output is sent to the browser. So your problem here is your debug code that is echoing output before you apply your change
    This is not true of native php sessions, as well as most custom session handlers.

  8. #8
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,015
    Mentioned
    62 Post(s)
    Tagged
    0 Thread(s)
    This has been my experience with them though. Tell you what, if he applies the fix and it works chances are good that you're wrong. If it still fails to work then I'm wrong.

    The way I've written PHP for some time now all output is echoed on the last line of the program to avoid problems of this nature.

  9. #9
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the suggestion, but I tried it and did not change anything.

    I also output everything on the last line, but I do not use ob_start and ob_get_clean. I store each part of the web page in variables thenconcatenate them in a template that is echoed right at the end of the script.

    What is interesting is that the "last active" column in my session table in MySQL is updated when I do the ajax call, but the session data column is unchanged.
    Look at the following three lines for session_id, last_updated, and session_data.

    The first is after adding two products
    The second is after the ajax call
    The third is after hitting an "update" which posts the data.

    last_updated
    1243624388
    1243624659
    1243624706

    session_id
    bc22b97b080c1bf8c26422f7e08ef603
    bc22b97b080c1bf8c26422f7e08ef603
    bc22b97b080c1bf8c26422f7e08ef603

    session_data
    quote|a:2:{s:26:"13342-200905141315-DS1052D";s:1:"1";s:27:"13345-200905141315-DS1102CA";s:1:"1";}
    quote|a:2:{s:26:"13342-200905141315-DS1052D";s:1:"1";s:27:"13345-200905141315-DS1102CA";s:1:"1";}
    quote|a:2:{s:26:"13342-200905141315-DS1052D";s:1:"5";s:27:"13345-200905141315-DS1102CA";s:1:"2";}

  10. #10
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Keep in mind everyone here needs to make a whole lot of assumptions about how your custom session handler is programmed. An assumption of the native files based behavior is out the window.

    Consider doing some logging, to a file. Put debug statements throughout your session handling code so you can see which functions get called with which values for which request data. You could group debug statements per http request by using uniqid() once per request.

  11. #11
    SitePoint Member
    Join Date
    May 2008
    Posts
    16
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    did you check that session variable is not updated anywhere else but on the ajax page.?

  12. #12
    SitePoint Addict skunkbad's Avatar
    Join Date
    Apr 2008
    Location
    Temecula, CA
    Posts
    278
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The problem is, the php script doesn't receive a cookie, letting it know that session data on the server is associated with the ajax call. You are going to have to pass your session cookie id to the php script within the headers of your ajax call:

    Code:
    <?php echo "http.setRequestHeader('Cookie','yourcookiename=" . session_id() . "');''; ?>
    This assumes you are generating the ajax within php, but you will need to get the cookie value to the php script, or it will never work.
    Last edited by skunkbad; May 30, 2009 at 21:47. Reason: code tags inserted

  13. #13
    SitePoint Wizard TheRedDevil's Avatar
    Join Date
    Sep 2004
    Location
    Norway
    Posts
    1,196
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    I am a little confused why you pass along the session id? And also why some people recommend you need to pass along a cookie manually?

    By default neither of those are needed, as the cookie (which usally contain the session id, unless disabled on the server) is passed along on every web request if its set on that location on the server.

    The issue is caused by the session handler/system. You mentioned its stored in the database, how does your session handler look and how is it called?

    If you have not tried it yet, revert back to the filebased session system just to test if it works as expected then.

    If it works then, its possible you might need to register a shutdown method for the session handler or there is a issue/bug in the session handler.

    Note, you also might want to validate the data to assure its something you expect. I.e. is it a valid product, is the product available etc etc. As the way it is now, I can easily order products that are for example no longer available. This could again get you into a pickle if you display a confirmation page and charge the CC at once, as you have entered a legal agreement to deliver said product.

    Michael Morris:
    You can change the Session data even after the headers has been sent. If your not able to do this, its most probably an issue with your script. Keep in mind that depending on your session handeling you sometimes need to register the shutdown method.

  14. #14
    SitePoint Enthusiast
    Join Date
    Sep 2005
    Posts
    68
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by agentforte View Post
    Thanks for the suggestion, but I tried it and did not change anything.

    I also output everything on the last line, but I do not use ob_start and ob_get_clean. I store each part of the web page in variables thenconcatenate them in a template that is echoed right at the end of the script.

    What is interesting is that the "last active" column in my session table in MySQL is updated when I do the ajax call, but the session data column is unchanged.
    Look at the following three lines for session_id, last_updated, and session_data.

    The first is after adding two products
    The second is after the ajax call
    The third is after hitting an "update" which posts the data.

    last_updated
    1243624388
    1243624659
    1243624706

    session_id
    bc22b97b080c1bf8c26422f7e08ef603
    bc22b97b080c1bf8c26422f7e08ef603
    bc22b97b080c1bf8c26422f7e08ef603
    session_data
    quote|a:2:{s:26:"13342-200905141315-DS1052D";s:1:"1";s:27:"13345-200905141315-DS1102CA";s:1:"1";}
    quote|a:2:{s:26:"13342-200905141315-DS1052D";s:1:"1";s:27:"13345-200905141315-DS1102CA";s:1:"1";}
    quote|a:2:{s:26:"13342-200905141315-DS1052D";s:1:"5";s:27:"13345-200905141315-DS1102CA";s:1:"2";}
    It looks like your AJAX call passes the sessionid just fine.
    Setting the session ID is not needed. XHR sends any cookies for the given domain it sends the HTTP Request to just like a normal page load.

    It looks like the problem is your handling the request made through XHR on the server side. What is the request, does it really do an update to the session data?

    Do you have any way of getting the HTTP Request and response? eg: Firebug, Wireshark etc.?
    Fiji Web Design - Enterprise Web Design

  15. #15
    rajug.replace('Raju Gautam'); bronze trophy Raju Gautam's Avatar
    Join Date
    Oct 2006
    Location
    Kathmandu, Nepal
    Posts
    4,013
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Look at the following example code which updates the session variable as expected and i hope this will help you out.
    Code php:
    <?php
    session_start();
    if(!isset($_SESSION['quantity']))
    	$_SESSION['quantity'] = '100';
    ?>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    	<title>AJAX Autoload</title>
    </head>
    <script type="text/javascript">
    var strLoading = '<div style="padding:2px;color:#FF0000;"><img src="ajax-loader.gif" border="0" /> Loading...</div>';
    function sendGetRequest(para_url, contentDiv, divLoading){
    	var url = "";
    	var xmlHttp = GetXmlHttpObject();
    	if(para_url.indexOf('?')) url = para_url + "&rand=" + Math.random();
    	else url = para_url + "?rand=" + Math.random();
     
    	xmlHttp.onreadystatechange = function(){
    		afterStateChange(xmlHttp, contentDiv, divLoading);
    	}
    	xmlHttp.open("GET", url, true);
    	xmlHttp.send(null);
    }
     
    function afterStateChange(xmlHttp, contentDiv, divLoading){ 
    	if(xmlHttp.readyState < 4){
    		showLoading('On', contentDiv, divLoading);
    	}
    	if(xmlHttp.readyState == 4 || xmlHttp.readyState == "complete"){
    		showLoading('Off', contentDiv, divLoading);
    		document.getElementById(contentDiv).innerHTML 	= xmlHttp.responseText
    	}
    }
     
    function showLoading(flag, contentDiv, divLoading){ 
    	if(divLoading != ''){
    		var objLoading = document.getElementById(divLoading);
    		if(!objLoading) var objLoading = document.getElementById(contentDiv);
    		if(flag == 'On') objLoading.innerHTML = strLoading;
    		else if(flag == 'Off') objLoading.innerHTML = '';
    	}
    }
     
    function GetXmlHttpObject(){
    	var xmlHttp;
    	try{
    		/* Firefox, Opera 8.0+, Safari */
    		xmlHttp = new XMLHttpRequest();
    	}
    	catch (e){
    		/* Internet Explorer */
    		try{
    			xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    		}
    		catch(e){
    			try{
    				xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    			}
    			catch (e){
    				alert("Your browser does not support AJAX!");
    				return false;
    			}
    		}
    	}
    	return xmlHttp;
    }
    </script>
    <body>
    <div id="showStatus"></div>
    <form name="frm1" id="frm1">
    Quantity: <input type="text" name="qty" id="qty" value="<?php echo $_SESSION['quantity'];?>" /> <br />
    <input type="button" value="Update Quantity" name="btnQty" id="btnQty" onclick="sendGetRequest('update.php?sess=<?php echo session_id();?>', 'showStatus', 'showStatus');" />
    <input type="button" value="Reload Page" name="btnReload" id="btnReload" onclick="document.location='./';" />
    </form>
    </body>
    </html>

    update.php
    Code php:
    session_start();
    session_id($_GET['sess']);
    $_SESSION['quantity'] += 1;
    echo '<span style="color: green;">Quantity was updated to : ' . $_SESSION['quantity'] . '</span>';
    Last edited by Raju Gautam; Jun 1, 2009 at 01:01.
    Mistakes are proof that you are trying.....
    ------------------------------------------------------------------------
    PSD to HTML - SlicingArt.com | Personal Blog | ZCE - PHP 5

  16. #16
    SitePoint Addict skunkbad's Avatar
    Join Date
    Apr 2008
    Location
    Temecula, CA
    Posts
    278
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @rajug:

    I don't think your code will work unless you put more copyright info

  17. #17
    rajug.replace('Raju Gautam'); bronze trophy Raju Gautam's Avatar
    Join Date
    Oct 2006
    Location
    Kathmandu, Nepal
    Posts
    4,013
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by skunkbad View Post
    @rajug:

    I don't think your code will work unless you put more copyright info
    What do you mean? You can use the code or even modify and sell if you want...
    Mistakes are proof that you are trying.....
    ------------------------------------------------------------------------
    PSD to HTML - SlicingArt.com | Personal Blog | ZCE - PHP 5

  18. #18
    SitePoint Addict skunkbad's Avatar
    Join Date
    Apr 2008
    Location
    Temecula, CA
    Posts
    278
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by rajug View Post
    What do you mean? You can use the code or even modify and sell if you want...
    I was joking. There is a lot of copyright info in your code, so I was laughing because it is more than the code!

  19. #19
    SitePoint Enthusiast
    Join Date
    Dec 2003
    Location
    norway
    Posts
    61
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As a some poster said calling session_id with a parameter is not needed,
    and will acutally create a new session..which could explain this

  20. #20
    SitePoint Addict skunkbad's Avatar
    Join Date
    Apr 2008
    Location
    Temecula, CA
    Posts
    278
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's another thing that helped me recently, and I don't know if it applies to you. If the php script is only updating a session, and isn't sending anything back to the browser, you will still need to have the php script send a 200 - OK header, and a space character or some sort of data. In my case, it was only certain browsers, but these browsers weren't "seeing" any response from the php script until I did what I am saying.

    The script I am talking about is the theme changer script on my website.

  21. #21
    SitePoint Wizard TheRedDevil's Avatar
    Join Date
    Sep 2004
    Location
    Norway
    Posts
    1,196
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by skunkbad View Post
    Here's another thing that helped me recently, and I don't know if it applies to you. If the php script is only updating a session, and isn't sending anything back to the browser, you will still need to have the php script send a 200 - OK header, and a space character or some sort of data. In my case, it was only certain browsers, but these browsers weren't "seeing" any response from the php script until I did what I am saying.

    The script I am talking about is the theme changer script on my website.
    Any request will return a header code.

    By default 200 OK is returned on every request that finishes running on the server, you dont need to send any output, its sent by default by the webserver.

    The same if any "failure" happens, the according header is sent.

    This is why you must make certain you send the correct failure headers on for example IPN scripts if there were a failure and you want the payment processor to send another request later (if the processor supports it of course).

    If you dont mind, I am really interested in what web server/version that this was on as well as what browser/version we are talking about.

    Thanks

  22. #22
    SitePoint Addict skunkbad's Avatar
    Join Date
    Apr 2008
    Location
    Temecula, CA
    Posts
    278
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TheRedDevil View Post
    Any request will return a header code.

    By default 200 OK is returned on every request that finishes running on the server, you dont need to send any output, its sent by default by the webserver.

    The same if any "failure" happens, the according header is sent.

    This is why you must make certain you send the correct failure headers on for example IPN scripts if there were a failure and you want the payment processor to send another request later (if the processor supports it of course).

    If you dont mind, I am really interested in what web server/version that this was on as well as what browser/version we are talking about.

    Thanks
    The server I am on is linux w/ php 5.2.6 @ inmotionhosting.com. The browsers that weren't working were:

    FF3 on Ubuntu 8.10
    FF3 on Mac OSX current
    Safari on Mac OSX current

    All Windows browsers worked that I tested (FF3, Opera, IE, Chrome). I'm all for things working the way they are supposed to, but sometimes they dont... and I just try things until they do.
    Last edited by skunkbad; Jun 1, 2009 at 12:23. Reason: additional info

  23. #23
    SitePoint Wizard TheRedDevil's Avatar
    Join Date
    Sep 2004
    Location
    Norway
    Posts
    1,196
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by skunkbad View Post
    The server I am on is linux w/ php 5.2.6 @ inmotionhosting.com.
    Is it running Apache, or do you a other application as the web server?

  24. #24
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I know that my problem has nothing to do with the session handler because sessions are handled properly by my application without ajax. I also used a custom session handler that was in the sitepoint PHP Anthology book.

    skunkbad, your solution is the only one I have not tried. It looks like that has a good chance of solving my problem. Unfortunately I get an error "http is not defined" when using the line:

    PHP Code:
    <?php echo "http.setRequestHeader('Cookie','yourcookiename=" session_id() . "');''; ?>
    Any tips? Note that I changed "yourcookiename" using the value echoed by session_name().


    Here is the ajax call that I use (after creating the URL, which works as expected when I copy it into the address bar. For some reason it does not work when called by javascript. I have a feeling this has to do with the client side storing a cookie which is not updated by ajax):

    HTML Code:
    	// Create new JS element
    	var jsel = document.createElement('SCRIPT');
    	jsel.type = 'text/javascript';
    	jsel.src = url;
    
    	// Append JS element (therefore executing the 'AJAX' call)
    	document.body.appendChild (jsel);
    I find this is much more elegant than using an ActiveXObject as shown by rajug.

  25. #25
    SitePoint Addict skunkbad's Avatar
    Join Date
    Apr 2008
    Location
    Temecula, CA
    Posts
    278
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TheRedDevil View Post
    Is it running Apache, or do you a other application as the web server?
    Yes, it is Apache


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •