我对PHP Post/Redirect/Get感到困惑

我对PHP Post/Redirect/Get感到困惑,php,html,forms,post,get,Php,Html,Forms,Post,Get,在一篇关于防止重新提交PHP表单的文章中,我阅读了以下内容: (不引用)这可能是接收表单数据的页面,例如称为“form.php”: 但是,用户不能导航到上面的URL吗?另外,GET变量的用途是什么?难道我不能在form.php上有一个脚本来检查用户是否登录了吗 在submit.php中,我是否应该将登录的用户名保存为$\u SESSION['username'],然后检查form.php中的isset()是否正确?此外,由于一个带有“success”的URL并不漂亮,再次重定向用户是否经济?我应

在一篇关于防止重新提交PHP表单的文章中,我阅读了以下内容:

(不引用)这可能是接收表单数据的页面,例如称为“form.php”:


但是,用户不能导航到上面的URL吗?另外,GET变量的用途是什么?难道我不能在form.php上有一个脚本来检查用户是否登录了吗

在submit.php中,我是否应该将登录的用户名保存为$\u SESSION['username'],然后检查form.php中的isset()是否正确?此外,由于一个带有“success”的URL并不漂亮,再次重定向用户是否经济?我应该使用PHP header()还是Javascriptwindow.location.href?正如您所见,我有点困惑

谢谢你的帮助


但是,用户不能导航到上面的URL吗

是的,他能。但这不会导致任何不好的结果

另外,GET变量的用途是什么

若要使用一些标志来表示表单已成功处理,您需要向用户表示祝贺

难道我不能在form.php上有一个脚本来检查用户是否登录了吗

嗯,您可以按照自己喜欢的方式保存代码。没有任何强烈的要求

在submit.php中,我是否应该将登录的用户名保存为$_SESSION['username'],然后检查form.php中的isset()是否正确

如果您需要在当前会话中保持它-是的,请这样做

此外,由于一个带有“success”的URL并不漂亮,再次重定向用户是否经济

重定向到哪里。重定向是非常便宜的事情

我应该使用PHP header()还是Javascript window.location.href


你绝对应该在php中这样做,否则你会遇到你试图避免的问题。是的,你永远不应该依赖get变量(甚至隐藏的POST变量)来说,“当然,让我进来,我是一个有效的用户!”

就我个人而言,我会去掉链接中的GET信息,只依赖会话变量。记住放置一个“session_start();”作为第一行代码,如果您使用PHP激活会话

对于submit.php:

<?php
session_start();
if ($_POST['user'] && $_POST['pass']) { // Make sure both variable are set
 if (your_method) {
 // Code to check if the user and pass are valid however you plan
  $_SESSION['user'] = $_POST['user'];
  $_SESSION['loggedin'] = time();
 }
}
header('Location: form.php'); // Either way, pass or fail, return to form.php
exit();
?>

然后在form.php中:

<form action="submit.php">
  <input type="text" name="user" required />
  <input type="password" name="pass" required />
  <input type="submit" value="Log in" />
</form>
<?php
session_start();
$activeuser = false;
if ($_SESSION['user'] && $_SESSION['loggedin'] < (time()+600)) {
// Check if the user exists and the last access was with in 10 minutes.
 $_SESSION['loggedin'] = time(); // If so, keep them up to date!
 $activeuser = true;
}
if ($activeuser) {
 // whatever should show to someone logged in
} else {
 // Show log in form
}
?>

另外,您可能已经知道这一点,但是默认的传输方法是GET,因此请确保在表单标记中指定method=“post”


如果需要的话,通常最好使用header()重定向,因为Javascript是客户端的,可以避免,这会破坏您对站点运行的意图。

正如您链接的文章所指出的,POST/redirect/GET背后的主要思想是避免用户重新提交数据(大多数时候)。一般来说,你不希望同一个帖子(数据完全相同)发生两次——事实上,在某些情况下,它可能会第二次执行某些操作(比如向信用卡收费),这是不好的

您在问题中询问的大部分内容都是实现细节(比如在重定向中发送?success请求参数)

在实践中,通常发生的情况是成功时重定向。例如,如果用户的输入未通过验证,则不重定向,而是重新显示表单以及相关的错误消息

这里是一个基本的例子,全部在一个脚本中。我试着只包括重要的东西,尽量少一些无关的东西

login.php

<?php
/**
 * ensure user supplied both username & password
 * @return mixed true or an array of error messages
 */ 
function validate_login_values($vars){
    $errors = array();
    if (empty($vars['username'])) $errors[] = 'You must supply a username, genius.';
    if (empty($vars['password'])) $errors[] = 'You must supply a password, dummy.';
    if (empty($errors)) return true;
    return $errors; // $errors must be an array.
}

if (! empty($_POST)){
    $validationResults = validate_login_values($_POST);
    if ($validationResults === true){
        // assume here that authenticate properly escapes it's arguments before sending them
        // to the database.
        if (authenticate($_POST['username'],$_POST['password'])){
            //GREAT SUCCESS!  The user is now logged in.  Redirect to home page
            header("Location: /");
            die();
        }
        $errors[] = 'Invalid username/password.  Try again, slim";

    }else{
        $errors = $validationResults; // validate_login_values created errors.
    }  
}
?>

<h1>Log In, Friend!</h1>]

<?php 
//display errors, if there were any
if (! empty($errors)): ?>
<div class="errors">Something went horribly wrong:
<ul><?php foreach($errors as $e) echo "<li>$e</li>"; ?></ul>
<div>
<?php endif; ?>

<form method="POST">
<!--   //username, password, and submit   -->
</form>

PRG或Post/Redirect/Get只是一种可以用来阻止消息框的模式。如何详细使用它(本文仅提供一般性建议)取决于您的需要

如果您想在cookie、会话或get变量中标记success flash消息,这完全取决于您自己。顺便说一句,第二次重定向不会有帮助,如果你玩它,你会学到这一点

唯一重要的部分是,在收到POST请求后,执行重定向。用户仍然可以在历史记录中前后移动,而不需要重新提交POST数据

这种模式很有效,是件好事。就在两天前,我又做了一次,一个循序渐进的weppapp安装程序更适合使用浏览器界面导航

关于您的重定向

此代码错误:

header('Location:/login/form.php?success=true');
首先,在冒号后面需要有一个空格:

header('Location: /login/form.php?success=true');
那么地址必须是绝对URI,它必须包含完整URL:

header('Location: http://example.com/login/form.php?success=true');
标题()旁边,您应该按照RFC提供一个消息正文,许多所谓的“web开发人员”甚至不知道:

$url = 'http://example.com/login/form.php?success=true';
header(sprintf('Location: %s', $url));
printf('<a href="%s">Moved</a>.', $url);
exit;
你找到了


重述一下:重要的是,在发布后进行重定向。其他一切,如传递变量,完全取决于您希望如何执行。

“但是,用户不能导航到上面的URL吗?”——是的,他可以。那么?你是对的,没有POST数据不会造成任何伤害。url中的
?成功
,没有什么比这更难看的了。我一直在使用类似的东西,因为大多数人都不注意这一点,而且这非常简单。我假设该示例中的查询字符串用于
form.php
来确定是否应该显示成功消息。如果您愿意,您可以在会话中执行此类操作。重要的是有一个重定向,因此重新加载不会重新执行POST,只是无害地进入成功页面。@user805556:这是任何形式的通用解决方案,例如添加评论形式。在这种情况下,检查消息是否已成功添加并不像
if(isset($\u SESSION…
Ok)那样简单,这会让它变得清晰一些。但是,由于我从不使用单独的登录页面,而是在每个页面上都有它们,我是否应该重定向到以下位置:?“submit.php?page=whather.php”然后使用该变量重定向回该特定页面?还有,如何在PHP中找到当前页面,以便
$url = 'http://example.com/login/form.php?success=true';
header(sprintf('Location: %s', $url));
printf('<a href="%s">Moved</a>.', $url);
exit;
http_redirect('/login/form.php?success=true');