title: Curing the "Back Button Blues"
body: <p>Ever stumbled on a tutorial that you feel is of great value but not quite explained properly? That's my dilemma. I know <a href="http://www.tonymarston.net/php-mysql/backbuttonblues.html" rel="nofollow noreferrer">THIS TUTORIAL</a> has some value but I just can't get it. </p>
  
  <ol>
  <li>Where do you call each function?</li>
  <li>Which function should be called
  first and which next, and which
  third?</li>
  <li>Will all functions be called in all files in an application?</li>
  <li>Does anyone know of a better way cure the "Back Button Blues"?</li>
  </ol>
  
  <p>I'm wondering if this will stir some good conversation that includes the author of the article. The part I'm particularly interested in is controlling the back button in order to prevent form duplicate entries into a database when the back button is pressed. Basically, you want to control the back button by calling the following three functions during the execution of the scripts in your application. In what order exactly to call the functions (see questions above) is not clear from the tutorial.</p>
  
  <blockquote>
    <p>All forwards movement is performed by
    using my scriptNext function. This is
    called within the current script in
    order to activate the new script.</p>
  
  <pre><code>function scriptNext($script_id)
  // proceed forwards to a new script
  {
     if (empty($script_id)) {
        trigger_error("script id is not defined", E_USER_ERROR);
     } // if
  
     // get list of screens used in this session
     $page_stack = $_SESSION['page_stack'];
     if (in_array($script_id, $page_stack)) {
        // remove this item and any following items from the stack array
        do {
           $last = array_pop($page_stack);
        } while ($last != $script_id);
     } // if
  
     // add next script to end of array and update session data
     $page_stack[] = $script_id;
     $_SESSION['page_stack'] = $page_stack;
  
     // now pass control to the designated script
     $location = 'http://' .$_SERVER['HTTP_HOST'] .$script_id;
     header('Location: ' .$location); 
     exit;
  
  } // scriptNext
  </code></pre>
    
    <p>When any script has finished its
    processing it terminates by calling my
    scriptPrevious function. This will
    drop the current script from the end
    of the stack array and reactivate the
    previous script in the array.</p>
  
  <pre><code>function scriptPrevious()
  // go back to the previous script (as defined in PAGE_STACK)
  {
     // get id of current script
     $script_id = $_SERVER['PHP_SELF'];
  
     // get list of screens used in this session
     $page_stack = $_SESSION['page_stack'];
     if (in_array($script_id, $page_stack)) {
        // remove this item and any following items from the stack array
        do {
           $last = array_pop($page_stack);
        } while ($last != $script_id);
        // update session data
        $_SESSION['page_stack'] = $page_stack;
     } // if
  
     if (count($page_stack) &gt; 0) {
        $previous = array_pop($page_stack);
        // reactivate previous script
        $location = 'http://' .$_SERVER['HTTP_HOST'] .$previous;
     } else {
        // no previous scripts, so terminate session
        session_unset();
        session_destroy();
        // revert to default start page
        $location = 'http://' .$_SERVER['HTTP_HOST'] .'/index.php';
     } // if
  
     header('Location: ' .$location); 
     exit;
  
  } // scriptPrevious
  </code></pre>
    
    <p>Whenever a script is activated, which
    can be either through the scriptNext
    or scriptPrevious functions, or
    because of the BACK button in the
    browser, it will call the following
    function to verify that it is the
    current script according to the
    contents of the program stack and take
    appropriate action if it is not.</p>
  
  <pre><code>function initSession()
  // initialise session data
  {
     // get program stack
     if (isset($_SESSION['page_stack'])) {
        // use existing stack
        $page_stack = $_SESSION['page_stack'];
     } else {
        // create new stack which starts with current script
        $page_stack[] = $_SERVER['PHP_SELF'];
        $_SESSION['page_stack'] = $page_stack;
     } // if
  
     // check that this script is at the end of the current stack
     $actual = $_SERVER['PHP_SELF'];
     $expected = $page_stack[count($page_stack)-1];
     if ($expected != $actual) {
        if (in_array($actual, $page_stack)) {// script is within current stack, so remove anything which follows
        while ($page_stack[count($page_stack)-1] != $actual ) {
              $null = array_pop($page_stack);
           } // while
           $_SESSION['page_stack'] = $page_stack;
        } // if
        // set script id to last entry in program stack
        $actual = $page_stack[count($page_stack)-1];
        $location = 'http://' .$_SERVER['HTTP_HOST'] .$actual;
        header('Location: ' .$location);
        exit;
     } // if
  
     ... // continue processing
  
  } // initSession
  </code></pre>
    
    <p>The action taken depends on whether
    the current script exists within the
    program stack or not. There are three
    possibilities:</p>
    
    <ul>
    <li>The current script is not in the $page_stack array, in which case it is
    not allowed to continue. Instead it is
    replaced by the script which is at the
    end of the array.</li>
    <li>The current script is in the
    $page_stack array, but it is not the
    last entry. In this case all
    following entries in the array are
    removed.</li>
    <li>The current script is the last entry
    in the $page_stack array. This is
    the expected situation. Drinks all
    round!</li>
    </ul>
  </blockquote>