Reputation: 40215
I have found many sites that describes PRG, but no simple PHP code example.
Here's what I implemented:
form.php
has an action: validate.php
.validate.php
is never seen by the user; if validates all $_GET
and, if valid writes it to database and generates the HTML of a confirmation page / if not valid, it generates the HTML of an error page explaining what is wrong. $_SESSION
variable and then validate.php
calls header('Location: <as appropriate>);
.submitted.php
of invalid_input.php
(in case the user reads the URL) consists only of echo $_SESSION['form_html'];
.That seems to me like protection against both page reload and back button problems.
Did I goof by trying to reinvent the wheel?
Upvotes: 52
Views: 76056
Reputation: 8247
Simplest scenario:
<?php
if ($_POST) {
//validate the input
if (/* input is OK */) {
// Execute code (such as database updates) here.
// Redirect to this page.
header( "Location: {$_SERVER['REQUEST_URI']}", true, 303 );
exit();
}
}
?>
<html>
<!-- here goes your HTML page with a form -->
Use REQUEST_URI
. Do not use PHP_SELF
as in most CMS systems and frameworks PHP_SELF
would refer to /index.php
.
Upvotes: 90
Reputation: 9143
I would like to introduce you to a method that is often used on a greater scale and in much more detail in frameworks.
We have a file called index.php
.
index.php
and show a notification.<?php
if (!isset($_SESSION)) session_start();
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
switch ($_POST['submit']) {
case 'add':
// This is where our first POST will end up
// We can perform actions such as checking the data here
// After that we will add the POST data to a session
$_SESSION['postdata'] = $_POST;
// and unset the $_POST afterwards, to prevent refreshes from resubmitting.
unset($_POST);
// Now we will redirect...
header("Location: ".$_SERVER['PHP_SELF']);
break;
case 'confirm':
// We can now insert the data into the database or email it
// Then we will unset the session and redirect back
unset($_SESSION['postdata']);
// This is to display our notification
$_SESSION['success'] = true;
// And there we go again...
header("Location: ".$_SERVER['PHP_SELF']);
break;
}
// We will exit here because we don't want the script to execute any further.
exit;
}
?>
<?php if (isset($_SESSION['success']) && $_SESSION['success'] == true): ?>
<p>Our data has been processed succesfully</p>
<?php unset($_SESSION['success']); ?>
<?php endif; ?>
<?php if (isset($_SESSION['postdata'])): ?>
<p>
You want to add the following data:<br />
<pre><?php print_r($_SESSION['postdata']); ?></pre>
Is this correct?<br />
<form method="POST" action="<?= $_SERVER['PHP_SELF']; ?>">
<button type="submit" name="submit" value="confirm">Yes</button>
</form>
</p>
<?php else: ?>
<p>
<form method="POST" action="<?= $_SERVER['PHP_SELF']; ?>">
<input type="text" name="..."><br />
<input type="text" name="..."><br />
<input type="text" name="..."><br />
<input type="text" name="..."><br />
<button type="submit" name="submit" value="add">Add something</button>
</form>
</p>
<?php endif; ?>
Upvotes: 7
Reputation: 263
Here is form.php
<?php
session_start();
// 1) _____________________________________________ POST _____________________________
if ( count($_POST) ) {
$ermsg ='';
…
check data, write some data to database(s), set error message(s) if any
…
$userdata1 = $_POST['htUserdata1'];
$userdata2 = $_POST['htUserdata2'];
…
$_SESSION['PRG'] = array('field1'=>$userdata1,'field2'=>$userdata1,…,'ermsg'=>$ermsg);
session_write_close();
header('Location: ' . $_SERVER['REQUEST_URI'].'?z',true,303);
exit;
// 2) _____________________________________________ REDIRECT ________________________
} else if ( array_key_exists('PRG',$_SESSION) ) {
$userdata1 = $_SESSION['PRG']['field1'];
$userdata2 = $_SESSION['PRG']['field2'];
…
$ermsg = $_SESSION['PRG']['ermsg'];
unset($_SESSION['PRG']);
// 3) _____________________________________________ GET ______________________________
} else {
…
retrieve data from database(s)
…
$userdata1 = dbGet1();
$userdata2 = dbGet2();
…
$ermsg = '';
}
// 4) _____________________________________________ DISPLAY _________________________
?>
<!DOCTYPE html>
<html lang="fr">
…
<form method="post" action="form.php" accept-charset="utf-8">
<input id="htUserdata1" name="htUserdata1" type="text"/>
<input id="htUserdata2" name="htUserdata2" type="text"/>
…
</form>
<script language="javascript">
"use strict";
<?php
$G['htUserdata1'] = $userdata1;
$G['htUserdata2'] = $userdata2;
…
$G['ermsg'] = $ermsg;
$myJSON = json_encode($G);
echo "var G=$myJSON;";
?>
document.getElementById('htUserdata1').value = G.htUserdata1;
document.getElementById('htUserdata2').value = G.htUserdata2;
…
if ( G.ermsg !=='') alert(G.ermsg);
</script></body></html>
Upvotes: 4
Reputation: 3812
Caller.htm
<form method="post" action="Callee.php?Query1">
<input type="text" name="PostData" />
<input type="submit" value="Go" />
</form>
Callee.php (Is called twice.)
if ($_POST) {
header("Location: ". $_SERVER['REQUEST_URI']. 'Query2');
// PART1: Use $_POST and $_GET to execute database updates here...
// Now any display (i.e. echo or print) will come after the header.
// ...
die; // When done, GET 'myself' to execute PART2 below.
}
// PART2: Results page goes here...
echo 'PART 2 display output: '; var_dump($_GET);
Notice there are two query strings involved
Look what var_dump says about $_GET:
PART 2 display output: array(1) { ["Query1Query2"]=> string(0) "" }
Issues with putting header at the end of the POST section like this:
header("Location: ". $_SERVER['REQUEST_URI']. 'Query2'); die;
The php manual says: "Remember that header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP. It is a very common error to read code with include, or require, functions, or another file access function, and have spaces or empty lines that are output before header() is called. The same problem exists when using a single PHP/HTML file."
However if you need to build 'Query2' based on what happens in the POST section, it may need to be at the bottom of the POST section. This is ok, so long as you don't try to insert any echo's above it, not even for testing.
Upvotes: 3
Reputation: 17555
Browser
HTML form
method=POST
|
v
PHP app
reads $_POST
sends 303 header
|
v
Browser
receives header
redirected to
new page
|
v
PHP app
reads $_GET
does whatever
A common use is in login authentication. That's the process flow when user submits the login form. PHP app authenticates user via $_POST vars. Sends a 303 header back to browser when the user has successfully authenticated. So user is redirected to a new page.
Upvotes: 11
Reputation: 71240
A snippet of code:
if (count($_POST)) {
// process the POST data
// your code here- so for example to log a user in, register a new account..
// ...make a payment...etc
// redirect to the same page without the POST data, including any GET info you
// want, you could add a clause to detect whether processing the post data has
// been successful or not, depending on your needs
$get_info = "?status=success";
// if not using rewrite
// header("Location: ".$_SERVER['PHP_SELF'].$get_info);
// if using apache rewrite
header("Location: ".$_SERVER['REQUEST_URI'].$get_info);
exit();
}
Upvotes: 30