Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Session not written after Output(echo or print_r on external ajax Call)

I´m having some serious trouble debugging this particular problem and I hope someone has a clue what i´m doing wrong.

I have a Custom CMS system working that uses Paragraphs as building blocks that get updated using Ajax(prototypejs) calls and functions that parse the HTML chunks in given order, clean them up and save this data in associative arrays in a Session variable. Users log in, Session is created and I can check for this session without problem in every page I need it. The system works directly on the definitive websites, so the user can see his updates on realtime and browse the site as a normal user would do, but editing. So, nothing new here. But here is the weird thing.

Enduser site on edit mode(admin user logged in): path "/"

After the logged status is verified, a function processes the editable content and saves an associative array to session, it also starts some javascript objects for editing every paragraph. Data is actually saved, I can use an external script to check if it´s there after this php script ends.If I load a new page(new content), Session gets updated with new data)

Admin User modifies a paragraph using an Inplaceeditor and this HTML chunk is send via Ajax to a php script that starts the named session, reads the present session data, checks if a paragraph should be modified, appended or deleted and reassigns values to existing array keys in $_SESSION. if i make a var_dump() o print_r to $_SESSION after assigning new data is there.After that the script echoes the processed html, and ajax updates the original paragraph on the calling page.

This script is in /admin/cms/...etc, that means at least 4 directories inside the root of the site.

When the script ends, I check using the same session dump script to see if data was really written/commited, but no, $_SESSION has only the original data from the calling page. Same ID, same session name, same session_start() but no data gets written. This whole operation is very quick, so I though it could be a speed problem, scripts ends before session_write_close can make his work.

But if I add a new key to $_SESSION array and put some data there, data gets updated and written. If i don´t output anything on this script and just process data and set session variables it also get´s updated and written.

It´s like some members of $_SESSION array are getting blocked to update.

What i did to track this error and what i´m sure i´m not doing wrong.

  • 1.- register_globals are off of course
  • 2.- session_name() and session_start() are always present and in the given
    order. I used to have multiple
    session_start() -close on a same page
    to use several named sessions, but to refine the problem this is not longer so.
  • 3.- I use session_write_close() after session data is processed. Also
    tried without, letting php decide when to commit data, but no luck.
  • 4.- I`m using only cookies for SID.
  • 5.- sessions are stored on /tmp, i can see the data getting updated.
  • I also tried using a custom save handler on DB, but same problem,
    "_write" got only called when no output as present.
  • I searched php.net, stackoverflow, google, etc for this subject. I never ask without investigation, this is my first time in many years...but it´s just so unlogical it must be something tiny a haven´t thought of.

The most weird thing is that when I just process data without output $_SESSION gets updated ok. But if i modify this script afterwards by adding the output and try again, instead of just having the new(last) value present I get the original value back, the one created by the calling page at first place, sometimes after playing around a few times! PHP can´t cache values between scripts or?I dont have globlals on.

I´m really clueless. This system worked flawless on PHP4.3, since i´m using 5.3.3 for two moths my users where caliming data where getting mixed up, so i checked and yes, there are serious problems. Today I updated to (5.3.6) and I can´t get this session values commited.

Script code called via Ajax:

<?
session_cache_limiter('nocache'); 
session_name("CMS_ses");
session_start();
include('../htmLawed/htmLawed.php');
include("utils_cms.php");
include("../../../php/utils_array.php");

$value=$_POST['value'];
$editorId=$_POST['editorId'];
$clase=$_POST['clase'];
$editorId=str_replace("pre","",$editorId);
$value=html_entity_decode(stripslashes($value),ENT_QUOTES);
if (strlen(trim($value))==0)
    {
    die();
    }
$value="<div id=\"$editorId\"  class=\"$clase\">$value</div>";

$newXHTML=$value;
$retorno=CMS_nuevoBloque($newXHTML,$editorId);
$_SESSION['data']['CMSeditores']=$retorno[1];   
$_SESSION['data']['CMScont']=$retorno[2];   
session_write_close();

print_r($retorno[0]); //Offending part...without everything works
?>

really nothing strange here....main page code is even simpler, no strange php directives, etc.

Here is the header of the caller page

include 'php/db.php';
$len=$_GET['len'];
$sec=$_GET['sec'];
$cont=$_GET['cont'];
$admfin=$_GET['admfin'];
$fecha=$_GET['fecha'];
$token=$_GET['token'];
$cur=$_GET['cur'];

$PHP_SELF=$_SERVER['PHP_SELF'];
session_cache_limiter('nocache');
session_name("CMS_ses");
session_start();

$passvar='';
unset($adm);
if ((!empty($_SESSION['cms_logged'])) and (!isset($admfin)) )
    {
    $nivelpermisos=$_SESSION['cms_logged_group'];
    $useractual=$_SESSION['cms_logged'];
    $adm=1;

    }
elseif (empty($_SESSION['cms_logged']))
    {
    unset($useractual);
    }
    //.........rest of the code  

UPDATE: I did late night tests and found someting i don´t understand.HElP please: It has not only to do with Sessions but also with Mysql Querys. Same code, but instead of trying to write to $_SESSION array i made a simple update to a Innodb table using the session_id. When i Output some code, the update does get executed,(i can output the query string and no mysql_error() or notice) problems, but checking the database the row doesn´t get updated. Letting the output out if the script and Query does get commited. Only common thing is sessions are started and output is made.

I restarted Apache, etc(who knows) but no luck. Then i made something really stupid, because this is a server side thing. I changed my browser to Firefox(using safari) and everything works! Ok, recheck, back to safari, nothing works. Both running side by side, same issue. PHP is server side, how can different browsers handle code different, can a browser say to apache rollback, request not handled or call the same script twice without notice(checked safaris developer console and the script is called only once) ? Can safari resubmit data silently because it "thinks" ajax failed? I checked headers using firebug and Safaris developer tools , nothing strange but whenever i make a Ajax call with safari, the caller page reloads data(Aka conection to server...).

I really don´t understand nothing.

like image 392
Diego Pino Navarro Avatar asked Apr 11 '11 21:04

Diego Pino Navarro


People also ask

What is PHP session_start () and Session_destroy () function?

session_destroy() function: It destroys the whole session rather destroying the variables. When session_start() is called, PHP sets the session cookie in browser. We need to delete the cookies also to completely destroy the session. Example: This example is used to destroying the session.

Why session_start () is used in PHP?

session_start() creates a session or resumes the current one based on a session identifier passed via a GET or POST request, or passed via a cookie. When session_start() is called or when a session auto starts, PHP will call the open and read session save handlers.

Do I need to call session_start on every page?

It must be on every page you intend to use. The variables contained in the session—such as username and favorite color—are set with $_SESSION, a global variable. In this example, the session_start function is positioned after a non-printing comment but before any HTML.

Where is $_ session stored?

The PHP session which is accessible via the global variable $_SESSION is stored on the server as files by default. Also the reference to it (called session_id ) is stored on client side as browser cookies.


2 Answers

I had a similar problem to this (if I have understood correctly). I needed to force session data to be written (for a custom session driver) after scripts have finished running. A shutdown function can be registered which should run after scripts have finished.

Maybe this will solve (or help you to solve) your problem.

http://php.net/manual/en/function.register-shutdown-function.php

like image 62
Lea Hayes Avatar answered Oct 07 '22 09:10

Lea Hayes


Thank's for your help. I was doing everything in the right order and still session data was not being written. Session names where necesary because sometimes we test many sites on the same domain using the same custom CMS. So, finally, after making lots of test and no luck, i found that register globals was active on this server(we never use it, code was written having this option off in mind of course), but it messes with sessions!. Switching this off made a huge change. No more problemas. I also made a custom session handler in DB, so i could track the problems in an more centralized way. Conclussion: Never use register globals + named sessions, an complex data in sessions. Anyway, i will give this issue more time and more tests. Ajax calls are also sometimes too fast, i had to put a sleep command so writing the session data was really done.Thanks

like image 26
Diego Pino Navarro Avatar answered Oct 07 '22 10:10

Diego Pino Navarro