2009-01-09 51 views
2

有没有偶然发现一个教程,你觉得它很有价值,但没有正确解释?这是我的困境。我知道THIS TUTORIAL有一定的价值,但我无法得到它。治愈“后退按钮布鲁斯”

  1. 你在哪里调用每个函数?
  2. 哪个函数应该叫做 先下哪个,哪个 第三?
  3. 将在应用程序的所有文件中调用所有函数吗?
  4. 有谁知道更好的方法治疗“后退按钮布鲁斯”?

我想知道这是否会引起包括文章作者在内的一些好的对话。我特别感兴趣的部分是控制后退按钮,以防止按下后退按钮时表单重复输入数据库。基本上,您希望通过在应用程序中执行脚本期间调用以下三个函数来控制后退按钮。教程中不清楚按照什么顺序调用函数(参见上面的问题)。

所有向前移动都是由 使用我的scriptNext函数执行的。这是在 的当前脚本中调用的 以激活新脚本。

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 

当任何脚本已经完成它的 处理它终止通过调用我的 scriptPrevious功能。这将使 从堆栈数组的末尾 中删除当前脚本,并重新激活数组中的前一个脚本。

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) > 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 

每当一个脚本被激活时,其 可以是通过scriptNext 或scriptPrevious功能或 因为返回按钮在 浏览器,它将调用下面 函数,以验证它是 当前脚本根据 程序堆栈的内容,如果不是,则采取 适当的操作。

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 

采取的行动取决于是否 的 程序堆栈或不存在内当前脚本。有三种 可能性:

  • 当前脚本不是$ page_stack阵中,在这种情况下是 不允许它继续。取而代之的是 替换为 末尾的脚本。
  • 当前脚本位于 $ page_stack数组中,但它不是最后一个条目的 。在这种情况下,所有 下面的条目中的条目都被删除,即 。
  • 当前脚本是$ page_stack数组中的最后一个条目 。这是 的预期情况。全部饮料 !

回答

0

我是为了防止形式重复条目到数据库中按下后退按钮时,控制返回按钮特别感兴趣的部分。

您的前提是错误的。如果您将应用程序设计为Web应用程序,则不存在“后退按钮布鲁斯”这样的事情。如果您设计的应用程序没有任何服务器端状态,则在第一种情况下,您将永远不会遇到此问题。这种极简主义的网络应用程序的工作非常好,通常称为REST。

0

@ troelskn

如果设计没有任何服务器端状态应用程序....

不可能设计出没有状态的有效应用,否则你有一些不相互沟通的单独页面。由于客户的维护状态充满了问题,因此没有有效的选择,只能维护服务器上的状态。

+0

嗨,很高兴你进来了。我解决了我的问题与post/redirect /获取模式在这里建议,但你可以请详细说明教程。我非常想更好地理解它。 – clientbucket 2009-01-10 08:01:08

+0

我不同意你,但基于经验,我相当肯定我们将无法以有意义的方式讨论这个问题。我只想说,除了你的观点之外,还有其他的观点,让人们找出他们自己的答案。 – troelskn 2009-01-10 14:55:55

0

@Marston。

我解决了post/redirect/get的问题,但我相信这个教程有一些优点,也许托尼马斯顿可以详细阐述它。以及它如何被用来解决不一定是我特别的问题,但可能是类似的东西。或者,如果这些函数实际上可以用于解决我的特定问题,那它比post/redirect/get更好。我认为这将成为这里社区的一个很好的补充。

3

如果你不明白我的文章,那么你应该仔细看看figure 1,它描述了一个典型的场景,用户通过一系列屏幕 - 登录,菜单,列表,搜索,添加和更新。当我描述FORWARDS的移动时,我的意思是当新屏幕被激活时当前屏幕暂停。当用户在当前屏幕中按下链接时会发生这种情况。当我将移动描述为BACKWARDS时,我的意思是用户终止当前屏幕(通过按下QUIT或SUBMIT按钮)并返回到前一个屏幕,该屏幕从停止的位置恢复处理。这可能包括合并在刚刚被终止的屏幕上所做的任何更改。

这是维护独立于浏览器历史记录的页面堆栈的关键 - 页面堆栈由应用程序维护并用于验证所有请求。就浏览器而言,这些可能是有效的,但可能会被应用程序识别为无效并据此处理。

页堆栈是由两个功能维持:

  • scriptNext()被用于处理 FORWARDS运动,这在叠层的末尾添加一个新 条目和 激活新条目。
  • scriptPrevious()用于处理 BACKWARDS移动,该操作从堆栈中删除 最后一个条目,并且 重新激活先前的条目。

现在以用户导航到LIST屏幕的第4页,进入ADD屏幕,然后返回到LIST屏幕的第5页为例的情况。 ADD屏幕中的最后一个操作是按下SUBMIT按钮,该按钮使用POST方法将详细信息发送到添加到数据库的服务器,之后它会自动终止并返回到LIST屏幕。

因此,如果您在LIST屏幕的第5页中按下BACK按钮,则浏览器历史记录将在ADD屏幕上生成最后一个操作的请求,该屏幕是POST。就浏览器而言,这是一个有效的请求,但与应用程序无关。应用程序如何判定请求无效?通过检查其页面堆栈。当添加屏幕被终止时,它的输入被从页面堆栈中删除,因此任何不在页面堆栈中的屏幕请求都可以被视为无效。在这种情况下,无效请求可以重定向到堆栈中的最后一个条目。因此

你的问题的答案应该是显而易见的:

  • 问:你在哪里调用每个函数?
  • 答:你所说的scriptNext() 功能,当用户选择 导航转发到一个新的屏幕, 并调用scriptPrevious()函数 当用户终止 当前屏幕。
  • 问:哪个函数首先应该叫 哪个下一个,哪个 第三?
  • 答:每个功能在 响应 用户选择的操作时被调用,因此一次只能使用一个功能 。
  • 问:是否所有的函数都会在 中被调用?
  • 答:应用程序中所有文件中的所有功能都应该可用 ,但只有在用户选择时才会调用 。

它你希望看到这些想法的行动,那么你可以下载我的sample application

0
if ($_POST) { 
    process_input($_POST); 
    header("Location: $_SERVER[HTTP_REFERER]"); 
    exit; 
}