Php 避免使用浏览器&x27;s后退按钮在前端控制器应用程序中重新提交表单

Php 避免使用浏览器&x27;s后退按钮在前端控制器应用程序中重新提交表单,php,forms,browser,controller,back,Php,Forms,Browser,Controller,Back,这是我的第一个PhP MySQL项目,也是我的第一个问题。我正在尝试制作一个小门户,为了学习基础知识,我正在尝试使用front controller模式,因为目前我对使用Observer模式没有信心 前端控制器基本上如下所示,并调用正确类的适当方法: $controller =''; $action =''; $queryString =''; parseURL($controller, $action, $queryString); $objView = new View; if ($cont

这是我的第一个PhP MySQL项目,也是我的第一个问题。我正在尝试制作一个小门户,为了学习基础知识,我正在尝试使用front controller模式,因为目前我对使用Observer模式没有信心

前端控制器基本上如下所示,并调用正确类的适当方法:

$controller =''; $action =''; $queryString ='';
parseURL($controller, $action, $queryString);
$objView = new View;
if ($controller == 'adminlogin' && $action == 'authenticate') {
    AdminLogin::getInstance()->authenticate();
} else if ($controller && $action) {
    SessionFactory::getSession();
    if (isset($_SESSION['userName'])) { // and some more validations
        callHook($controller, $action, $queryString);
    } else {
        $objView->assign('message', SESSION_INVALID);
        $objView->display('index');
    } 
} else {
    $objView->display('index');
}
视图也很简单:

public function assign ($variable, $value)
{
    $this->passArray[$variable] = $value;
}

public function display ($view)
{
    $mapper = ViewmapSingleton::getinstance();
    if (1 == preg_match("/\/|\.|\\\\/", $view)) {
        echo 'View name should not contain . / or \ ';
    }
    $template = $mapper->getViewPath($view);
    if (!$template || is_dir($template)) {
        echo 'The requested view file does not exist';
    } else {
        extract ($this->passArray);
        include_once($template);
    }
}
我的问题是提交$\u POST表单时浏览器的“后退”按钮。我试图制作一个管理页面,显示文章列表,允许分页、批量操作和“按标题/类别搜索文章”等

从我在这个(最有用的)网站上读到的内容来看,有两种解决方案可以防止浏览器的“后退”按钮重新提交表单:

解决方案1。通过使用搜索按钮上的Javascript将搜索参数附加到URL,将搜索参数传递给操作(方法)

<input id="btn1" type="submit" onclick="SubmitForm('index.php?   controller=articles&action=showList&articleTitle='+document.getElementById('articleTitle').value)" value="Search" name="btn1"></input>

=>这不是最好的方法,因为可能有很多参数,如文章类别等

解决方案2。不要传递参数,而是在被调用的方法中使用$\u POST数据。将所有内容保存在$\u会话中,然后使用header()重定向到同一类中的单独显示方法。从display函数中的$\会话中提取所有内容并生成视图

=>这不是最好的方法,因为可能有许多参数必须存储在会话中然后提取

在使用前端控制器时,是否有更优雅的方法防止浏览器的“后退”按钮重新提交表单?我这样问是因为在使用front controller模式时,$\u GET可能没有多大用处,特别是在某些批量操作需要更改DB并且属于“Unpublish”类型的情况下

请忽略我的无知,帮助我


谢谢

另一种方法是使用重定向

更新:请参阅此解决方案。 欢迎来到SO

首先,除非GET是绝对必要的,否则请始终使用POST提交表单。(详情见下文)

您的PHP代码应该完全依赖$\u POST来检索提交的数据($\u GET可能为空,而$\u请求结合了$\u GET和$\u POST)

应用程序接收表单数据并可能对其进行处理后,重定向浏览器。不要发送HTML响应,而是发送302移动,将浏览器引导到下一页:

一个非常基本的例子:

session_start();                                       // make sure a session is available
if (is_array($_POST) && array_key_exists('submitbutton_name', $_POST)) {
    // user has submitted the form
    $inputdata = $_POST;                               // retrieve input data
    $next_page_html = determine_next_page($inputdata); // process and construct next page
    $_SESSION['page_to_show'] = $next_page_html;       // keep the HTML response

    // redirect the browser to the very same location, but using GET
    header('Location: ' + $_SERVER['REQUEST_URI']);
    exit;
}

// the redirect will end up here
if (array_key_exists('page_to_show', $_SESSION)) {
    // we have a next page to show
    echo $_SESSION['next_page_to_show'];
    // don't forget to remove the session entry
    unset($_SESSION['next_page_to_show']);
}
else {
    // output the starting page, probably the form that the user should submit
}

好极了!我也不喜欢美元,你的解决方案很有魅力。只有一件小事:头('Location:'+$\u SERVER['REQUEST\u URI']);出口由于某种原因显示了一个空白页,但是,它做了一个小改动=>$uri=$\u服务器['REQUEST\u uri'];标题(“位置:$uri”);出口因为这是我的第一篇文章,我不确定我是应该把它作为一个独立的回应还是一个评论来写。欧内斯特,管理中的参数少了,上面的就可以了。但是,前端也使用前端控制器模式,并将所有请求定向到index.php,后者在适当的类中调用适当的方法。两个小问题:(1)如果我在前端也使用上述方法,那么即使没有必要,我是否应该在一开始就启动会话?(2)在构建购物车类型的站点时,前端可能有大量的参数。在这种情况下应该使用$\u GET还是$\u POST也可以处理?(3) $\u GET不会将$controller='something'&$action='something'放在URL中,因此它甚至可以用于需要控制器和操作名称的前端控制器中?通常,在更改/上载数据时使用POST,在检索数据时使用GET。POST没有GET doeas的限制,GET doeas的长度是有限的(请检查RFC)。由于您的购物车无论如何都需要一个会话,所以您可以直接启动它,并使用它存储当前重定向状态。OTOH,您可以重定向到类似SmartURL的东西,它实际上由index.php处理。SmartURL将在$\u服务器['PATH\u INFO']中提供。当所有请求都指向一个文件时(如在front controller模式中),参考讨论不会有多大帮助