Hello everyone!

First of all, let me thank you for reading this.

After that, I would like to explain my problem, to see if anyone gives me any clue…

I am experiencing troubles managing session variables in Drupal (the $_SESSION array in Php). I can say I have googled a lot and it seems to be a common problem, but none of the solutions seems to be suitable for me (and the ones that seem promising don’t work… At least, I couldn’t make them work)

I have a web form that is integrated in Drupal (I mean… that it is a Drupal node). Users can submit different things using different buttons in that form. When the user clicks on any “Submit” button, an external script (named “processor.php” ) is called (the definition of the form is the “typical”: <form enctype="multipart/form-data" action="processor.php" method="post"> ). Depending on the “submit” button that the user has clicked on, this “processor.php” reads the data stored in the $_POST array and fires some actions, like creating some classes (I am using OOP), initializing them and so on. Some of these objects created in the “processor.php” need to be “propagated” between different .php scripts using the $_SESSION array, but that array’s contents seem to be lost in one of these steps.

Let me explain it with an example: This is a form to allow people to send information about events that are going to take place in a future (concerts, exhibits… stuff like that). Among many other things, users need to choose the venue where the event is going to take place using a “Select” (a combo field). If the venue doesn’t appear in the listing (meaning, it is not in the database yet), the users have the chance of creating (or submitting, as you prefer to call it) a new venue. Therefore, one of the submit buttons is “Add Venue”. If the user fills the required fields properly, when he clicks the “Add Venue” button, it goes to “processor.php”, that instantiates a new “Venue” object, initializes it with the data received from the web form, inserts the “Venue” object it in the corresponding database and, finally places that object in the $_SESSION array and redirects the user to the main form (the Drupal node) again. The idea I had (and what was actually working until I integrated the web form in Drupal) is that when the form is displayed again, in the selects (combos) where the user has to choose the venue it would appear pre-selected the recently added venue. But it is not working. Tha has other implications, because I want to allow users to modify an already inserted venue, but I want to allow them to modify the venues they have actually added in the current session (I don’t want that everyone is able to randomly modify the venues’ information)

As I said, the form itself is a Drupal’s node. You can see it in: http://www.hectorblanco.org/drupal5/?q=en/node/14

The rest of the .php scripts are placed in a subdirectory called external/Formulario/ The complete path for them is [Drupal Root]/external/Formulario.

I read the information about the Bootstrap that I found in this link. I thought about following it, but I don’t want to place my scripts in the Drupal root. That would make a mess so I also tried to follow what says in http://agaric.com/note/access-drupal-functions-and-session-from-a-php-sc... , changing the number of characters to remove from 13 to 20 so it would work with /external/Formulario (instead of the /profiles/scf as it is displayed in the example) but it didn’t work either. It keeps saying that it can not find ./includes/boostrap.inc

I also tried to change the “[Drupal root directory]/sites/settings.php” as said in http://drupal.org/node/52306 but without luck.

I also tried to access directly the $user object (although as far as I have seen in the “sessions” behavior that doesn’t seem necessary, because my guess is that when someone uses $_SESSION, Drupal uses the $user->session array automatically and in a transparent for the user way)

Please… does any of you have a hint of how avoid the lost of the $_SESSION variables when I call to external scripts? I would appreciate anything you say… a link to a howto, a few lines of tips… anything

Thank you!!

Comments

geertv’s picture


$currdir=getcwd();
chdir($_SERVER['DOCUMENT_ROOT']);
require_once("./includes/bootstrap.inc");
drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
chdir($currdir);

// rest of your code...

BorrajaX’s picture

I like your approach. Now I can properly include the bootstrap.inc file, but it is still not working.

I have created a much simpler test. It is a little form (inside Drupal: http://www.hectorblanco.org/drupal5/?q=en/node/16) with a text field and a Submit button that when it's pressed, it calls an external .php script (./external/Test2/processor.php)

The external script only adds the value of the text field to the text array.

What surprises me is that the $user seems to be totally different when it is displayed in the node inside drupal (there it is the Webmaster) and when it is displayed in the external script (there is an anonymous user):

The code for the node that is inside Drupal is:

<?php
require_once("./includes/bootstrap.inc");
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
session_start();
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Test 2</title>
    </head>
    <body>


        <form enctype="multipart/form-data" action="http://hectorblanco.org/drupal5/external/Test2/processor.php" method="post">
            <label for='input_text'>Price of the event</label>
            <input type='text' name='input_text' id='input_text' value='0'/>
            <br />
            <input type="submit" name="send_button" id="send_button" value="Send>>" />
        </form>
        <?php
        session_start();
        if (!isset ($_SESSION['valores'])){
            session_register('valores');
        }
        Print "Contenido de \$_SESSION: <br />";
        Print "<pre>";
        print_r($_SESSION);
        Print "</pre>";
    Print "Testing global user: ";
    Print "<pre>";
    global $user;
    print_r($user);
    Print "</pre>";
        ?>
    </body>
</html>

And the content of the external node (processor.php) is:

<?php
$currdir=getcwd();
//Print "Current dir: $currdir <br/>";
//Print "Document root: " . $_SERVER['DOCUMENT_ROOT'] . "<br/>";
chdir($_SERVER['DOCUMENT_ROOT'] . "/drupal5/");
require_once("./includes/bootstrap.inc");
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
global $user;
//chdir($currdir);

/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
if (isset($_POST['send_button'])) {
    Print "Recibido: " . $_POST['input_text'] . "<br />";
    session_start();
    if (!isset ($_SESSION['valores'])){
        session_register('valores');
    }
    $_SESSION['valores'][] = $_POST['input_text'];
    Print "Contenido de \$_SESSION: <br />";
    Print "<pre>";
    print_r($_SESSION);
    Print "</pre>";
    Print "Testing user: ";
    Print "<pre>";
    print_r($user);
    Print "</pre>";
}
?>

But, as I said, the $user in both scripts seems totally unconnected.

I have also tried to do it with another browser in which I hadn't logged in (IE explorer) but still doesn't work.

BorrajaX’s picture

Got it!!!.

It was happening to me what is described here: http://drupal.org/node/212325#comment-716624

I discovered that the problem was that when calling the external script, (processor.php) the session id changed (if something happens, you can check it out using Print '<p>sessionid='.session_id().'</p>'; in your script.

The part that was a node in Drupal had a totally different session id than the external script. To avoid that, I edited the [drupal_root]/sites/default/settings.php and I set $base_url = 'http://www.hectorblanco.org/drupal5'; It had to be "drupal5" because in my case, Drupal is not installed in the root of the server, but in a subdirectory.

By doing that, the session Id didn't change among the calls to the external script. I am going to copy the code here, just in case someone may find it useful:

This is the code that is a Drupal node (http://www.hectorblanco.org/drupal5/?q=en/node/16)

<?php
if (!isset($_SESSION)){session_start();}
global $user; //This is just so it can be displayed. It should be removed if we don't want to print the information of the user
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Test 2</title>
    </head>
    <body>


        <form enctype="multipart/form-data" action="http://hectorblanco.org/drupal5/external/Test2/processor.php" method="post">
            <label for='input_text'>Price of the event</label>
            <input type='text' name='input_text' id='input_text' value='0'/>
            <br />
            <input type="submit" name="send_button" id="send_button" value="Send>>" />
        </form>
        <?php
Print '<p>sessionid='.session_id().'</p>';

if (!isset($_SESSION)){session_start();}

        if (!isset ($_SESSION['valores'])){
            session_register('valores');
            Print "Registering 'valores'";
        }
        Print "Contenido de \$_SESSION: <br />";
        Print "<pre>";
        print_r($_SESSION);
        Print "</pre>";
    Print "Testing global user: ";
    Print "<pre>";
    print_r($user);
    Print "</pre>";
        ?>
    </body>
</html>

And the external script that is called when the user presses the "submit" button (placed under [DRUPAL_ROOT]/external/Test2/processor.php) is

$currdir=getcwd();
//Print "Current dir: $currdir <br/>";
//Print "Document root: " . $_SERVER['DOCUMENT_ROOT'] . "<br/>";
chdir($_SERVER['DOCUMENT_ROOT'] . "/drupal5/");
require_once("./includes/bootstrap.inc");
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
try {
    Print '<p>sessionid='.session_id().'</p>';
} catch (Exception $e) {
}

//global $user;
chdir($currdir);
if (!isset($_SESSION)){session_start();}

/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
if (isset($_POST['send_button'])) {
    Print "Recibido: " . $_POST['input_text'] . "<br />";
    if (!isset ($_SESSION['valores'])){
        session_register('valores');
        Print "Registering 'valores'<br />";
    }
    $_SESSION['valores'][] = $_POST['input_text'];
    Print "Contenido de \$_SESSION: <br />";
    Print "<pre>";
    print_r($_SESSION);
    Print "</pre>";
    Print "Testing user: ";
    Print "<pre>";
    print_r($user);
    Print "</pre>";
}

Buff!! That took a while!! I hope it helps someone!

geertv’s picture

Ah yes... setting the correct drupal-root in settings.php..

We had a different problem using external javascripts on our website a while ago, which were solved after correctly setting the http-root. However that problem had nothing to do with session variables, so I hadn't related it to your problem, but it is good to know.

Good luck !

yukisan’s picture

Great work! Thank you so much, I've been struggling to find a solution too.

Baibhav Kumar’s picture

Thanks BorrajaX ,
You made my day your reply is awesome and working fine for me

Toonbye’s picture

Had the same problem in my Drupal 7, and had to change some code to make this solution work out.
You'll have to use the new bootstrp code found here :
https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/drupal...

in the end, you'll have these lines :

define('DRUPAL_ROOT', $_SERVER['DOCUMENT_ROOT'] . '/path/to/drupal');
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); // <<< could use DRUPAL_BOOTSTRAP_SESSION
try {
	Print '<p>sessionid='.session_id().'</p>';
} catch (Exception $e) {
}
chdir($currdir);
if (!isset($_SESSION)){session_start();}

if ( isset($_POST['my_var']) ) {
	$_SESSION['my_var'] = $_POST['my_var'];
}

Hope this helps