SitePoint Sponsor

User Tag List

Results 1 to 23 of 23
  1. #1
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Ghost Session Array Vars: unset will not rid my array elements

    Well, I finally broke down and came to the board for this problem.

    Here's the background:

    I have a session variable which is an associative array of objects. There are a set of subsequent form pages which the user goes through which modifies an individual object in that array by identifying the index with a $_GET variable. When the user submits the final form, a script is run and if the db insertion is successful, that particular session array variable is unset via:

    unset($_SESSION["example"][$elementid]);

    and the user is redirected to their homepage. My concern is if they decide to click the 'Back' button on the browser. To my amazement, if they go back to the last form page, a fatal error is output saying that the object does not exist, even though the element was unset.

    I ran the count() function at the very beginning of the last form page and I get "0". However, if I run the count() function within my main() function of that last form page before the script tries to access the obejct (I use a main() function for each page as a hacky template system), I am getting a "1" like the element is still there. The array element contains nothing, but is still referenced by the same $elementid that was unset.

    So, then I ran a redirect on this page to send the user back to another page which uses the session array, on the condition where the count == 0. Now, if I run a count on this session variable at the very beginning of this other page, I am getting "1", not "0" like before. Looking at the contents of the array variable, I see that the index is the exact one ($elementid) which I unset two pages back, but now it has an empty object again because I did unset it.

    My question boils down to, is there an inherent problem with PHP where unsetting a session array variable is not totally exhaustive? If this is the case, then I will have a huge problem because I need the script to run differently when there are no elements in the array (obviously, so it won't try to run member functions on an object that isn't there but the array index is present).

    I've also tried a little hack:

    if(count($_SESSION["examplearray"]) == 0)
    $_SESSION["examplearray"] = array();

    to reinitialize the array before the redirect, but the page is still remembering the variable somehow. Argh!

    So, does anyone have any suggestions of either getting around this? If you need more clarification, I can try an additional post. Putting the code here really wouldn't do any good as it is multiple pages and I'm sure it's not the code, just the way the server and PHP are interacting with my session variables.

    Peace,

    Justin

  2. #2
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    did you mean !=
    PHP Code:
    if(count($_SESSION["examplearray"]) != 0)
     
    $_SESSION["examplearray"] = array(); 
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  3. #3
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    did you mean !=
    PHP Code:
    if(count($_SESSION["examplearray"]) != 0)
     
    $_SESSION["examplearray"] = array(); 
    No, actually I didn't. If there are no more elements in the array, I figured the easiest way to totally clean it out of any chance of leftover variables was to reinitialize.

    If there are elements actually left in the array, I do not want to reinitialize. aka more items in a shopping cart type deal.

    This code was just a quick hack that didn't work either. I'm still stuck on the underlying problem of the session array element not being totally erased.

    Justin

  4. #4
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's something else to add I just figured. Using unset on the specific array element is supposed to actually remove that element, not just set the element's value to "", correct?

    Because it seems initially, when I unset the array element, that it is working because the count() returns "0". But after going to another page, the array element is left intact with the index I unset but the value of the array element is "".

    What gives?

    Justin

  5. #5
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Can you turn on
    PHP Code:
    error_reporting(E_ALL); 
    at the begining of your script? count() of an unset value does return 0, but it also is a Notice condition you should code around.

    Notice: Undefined index: bogus in /home/sweatje/public_html/test.php on line 6
    0

    PHP Code:
    error_reporting(E_ALL|E_STRICT);

    session_start();
    echo 
    count($_SESSION['bogus']), "\n"

  6. #6
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    Can you turn on
    PHP Code:
    error_reporting(E_ALL); 
    at the begining of your script? count() of an unset value does return 0, but it also is a Notice condition you should code around.

    Notice: Undefined index: bogus in /home/sweatje/public_html/test.php on line 6
    0

    PHP Code:
    error_reporting(E_ALL|E_STRICT);

    session_start();
    echo 
    count($_SESSION['bogus']), "\n"
    Jason,

    I think I might have just figured something out. I think I have to go back and check my array syntax. What I'm doing is using a product ID as the element id for each item in the array. I have to be sure I'm setting AND checking it as a string number and not an int number. That would explain why if I'm seeing an index of the same "number" I thought I unset with no value in the variable, PHP could be thinking regular, indexed array not associative array.

    What command would you suggest so that a stringed number will always appear when using arrays? to_string()?


    Justin

  7. #7
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In your case, it will not matter:
    PHP Code:
    $a = array();

    $a[(int)'100'] = 'one hundred';
    $a['200'] = 'two hundred';
    $a[300] = 'three hundred';
    var_dump('before'$a);
    unset(
    $a[(int)'200']);
    unset(
    $a['100']);
    var_dump('after'$a); 
    produces
    Code:
    string(6) "before"
    array(3) {
      [100]=>
      string(11) "one hundred"
      [200]=>
      string(11) "two hundred"
      [300]=>
      string(13) "three hundred"
    }
    string(5) "after"
    array(1) {
      [300]=>
      string(13) "three hundred"
    }

  8. #8
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    In your case, it will not matter:
    PHP Code:
    $a = array();

    $a[(int)'100'] = 'one hundred';
    $a['200'] = 'two hundred';
    $a[300] = 'three hundred';
    var_dump('before'$a);
    unset(
    $a[(int)'200']);
    unset(
    $a['100']);
    var_dump('after'$a); 
    produces
    Code:
    string(6) "before"
    array(3) {
      [100]=>
      string(11) "one hundred"
      [200]=>
      string(11) "two hundred"
      [300]=>
      string(13) "three hundred"
    }
    string(5) "after"
    array(1) {
      [300]=>
      string(13) "three hundred"
    }
    Yeah, I just found out the hard way after modifying all my checks and sets.

    What do you think the problem could be then? Why it's not being unset across the board?

    Justin

  9. #9
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by pinemind
    Yeah, I just found out the hard way after modifying all my checks and sets.

    What do you think the problem could be then? Why it's not being unset across the board?

    Justin
    Are you doing a session_start() before the unset()?

    -matt

  10. #10
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwmitchell
    Are you doing a session_start() before the unset()?

    -matt
    Matt,

    Yes, I am. I use a template system so I include a session.inc file everytime with the session_start command.

    It's unsetting correctly on one page, then for some reason, if I use the back button, on certain pages it acts like the element is still there WITHOUT the value . . .

    And since the value is an object, it results in errors because the object is not there.

    When unsetting an array element that contains an object, is there some more thorough way of going about it? This array of object works perfectly otherwise. Even when I run methods to unset the elements individually (empty certain items from a cart), the array acts normally. It only acts up when the user clicks on the 'Back' button in the browser. Are there things stored on the server in relation to the session variables that the 'Back' button doesn't override?

    Justin

  11. #11
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Back is probably using a locally cached copy of the page so it still might appear to be there. Hit refresh, if it goes away, then I might think you need to send out no-cache headers for you application.

  12. #12
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    Back is probably using a locally cached copy of the page so it still might appear to be there. Hit refresh, if it goes away, then I might think you need to send out no-cache headers for you application.
    Nope, the problem seems to occur like this. I have another variable to throw in here. My webhost has register globals set to ON. I don't ever use any globals, just the superglobals ($_etc).

    I found this on another forum and I wanted to know if anyone had heard of this technique. I'm just not sure how to implement it with a multiple array set up like mine:

    Code:
    function unreg_sess_var( string $element ) 
    { 
        if ( ini_get( 'register_globals' ) ) 
        { 
            session_unregister( $element ); 
        } 
        else 
        { 
            unset( $_SESSION[$element] ); 
        } 
    } 
    
    unreg_sess_var( $_SESSION['variable'] );  /* ( REPLACE WITH YOUR VARIABLE )---- */
    or . . .

    Code:
    unset( $_SESSION['variable'], $variable ); /* ( REPLACE WITH YOUR VARIABLE )---- */
    And the problem occurs between two key points. I run a count BEFORE I run my main() function. It returns "0". But inside the main function, where all the code and formatting happens, the session array magically remembers that single element without a value. So the problem must lie in:
    a) the unsetting of a session variable with register globals turned on
    b) something called between the beginning of my file and the main function (which I've checked, there's nothing abnormal, just runs any header scripts that need to be done before the main and then jumps right into the main)

    I'm gonna try these two methods.

  13. #13
    SitePoint Enthusiast DmS's Avatar
    Join Date
    Jan 2004
    Location
    Stockholm, Sweden
    Posts
    94
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No real time at this point, but I ran into something similar when I had arrays stored in sessions, then tried to unset them by looping the $_SESSION using a foreach which didn't work. If I remember correctly this was because foreach works with a copy of the array passed to it, so I was in fact unsetting the copy of the $_SESSION, not the session...

    Just a thought
    /Dan
    { knowledge is what remains once you forget what you learned }
    Home: DmSProject Tutorials: GurusNetwork
    Committed at:
    OzoneAsylum + Blog

  14. #14
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DmS
    No real time at this point, but I ran into something similar when I had arrays stored in sessions, then tried to unset them by looping the $_SESSION using a foreach which didn't work. If I remember correctly this was because foreach works with a copy of the array passed to it, so I was in fact unsetting the copy of the $_SESSION, not the session...

    Just a thought
    /Dan
    Makes sense, but I'm strictly doing this command:

    unset($_SESSION["CARTS"][$sid];

    It has to have something to do with cacheing and the 'back' button. I just don't understand how unsetting a superglobal can backfire even if it's a cached page. My script is still read because it passes an if statement where the count > 0, which it should not but it does because it has an index without a value.

    Unset does remove the entire array element, correct?

    I've been at this all last night and today, I'm about to lose it .. . .

    Justin

  15. #15
    SitePoint Enthusiast DmS's Avatar
    Join Date
    Jan 2004
    Location
    Stockholm, Sweden
    Posts
    94
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I took a quick look in the usernotes in the manual, here: http://www.php.net/manual/en/function.unset.php and there are quite a lot of references to places where you'd think you have unset the variables/sessions but they remain.
    You have read that havn't you?
    /Dan
    { knowledge is what remains once you forget what you learned }
    Home: DmSProject Tutorials: GurusNetwork
    Committed at:
    OzoneAsylum + Blog

  16. #16
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DmS
    I took a quick look in the usernotes in the manual, here: http://www.php.net/manual/en/function.unset.php and there are quite a lot of references to places where you'd think you have unset the variables/sessions but they remain.
    You have read that havn't you?
    /Dan
    Dan,

    I have read through that and the problem is, the manual says nothing pertaining to superglobals, which are quite different from globals that they talk about in that portion of the manual. Since $_SESSION["somevar"] is a superglobal, I had come to believe that no matter where it was unset, set or changed, that the effect would be across the board so to speak.

    That's why it's very odd, because caching shouldn't be an issue when your changing superglobals. Unless my isset() check on the specific element in the array somehow makes that element a variable again?? Can we say huge bug? j/k

    I think I'm delirious.

    Confused and frustrated,

    Justin

  17. #17
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    what about calling session_write() after the unset? I've had this happen to me before and I think this worked, but I still don't know why I had the problem...

    -matt

  18. #18
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwmitchell
    what about calling session_write() after the unset? I've had this happen to me before and I think this worked, but I still don't know why I had the problem...

    -matt
    Matt,

    Do you mean session_write_close()?

    Justin

  19. #19
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwmitchell
    what about calling session_write() after the unset? I've had this happen to me before and I think this worked, but I still don't know why I had the problem...

    -matt
    Tried session_write_close(). No dice, same deal.

    J.

  20. #20
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Did you
    PHP Code:
    exit(); 
    after the header('Location: ...'); line?

  21. #21
    SitePoint Enthusiast
    Join Date
    Jul 2003
    Location
    NJ
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    Did you
    PHP Code:
    exit(); 
    after the header('Location: ...'); line?
    Jason,

    Thanks for being my soma in these trying times. Turns out I didn't have any exit()'s on my header commands. I put them after all the redirects and boom, now they can click back all they want and no object errors, no mysterious session array reappearances.

    Thanks to everyone for putting up with my longwinded and persistent posts.

    One quick question, Jason maybe you can get this one:

    What purpose does exit() server after a header command is already issued?

    Is it good coding practice to use exit() after every header command?

    Thanks again everyone, now I can revel in the fact that I won't have to switch my object oriented session variable to quad dimension arrays.

    Peace,

    Justin

  22. #22
    SitePoint Enthusiast dodga's Avatar
    Join Date
    Apr 2004
    Location
    Germany
    Posts
    90
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What purpose does exit() server after a header command is already issued?
    Is it good coding practice to use exit() after every header command?
    Well, not really
    When issuing header('Location: ...'); you should call exit() or die() so that nothing else gets sent to the browser and the redirection takes place.
    Not calling exit() results in executing the rest of the PHP script which may be not what you want, YMMV though
    remember my name - you'll scream it later

  23. #23
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)


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
  •