Simple PHP Post-Redirect-Get code example
Simplest scenario:
if ($_POST) {
// Execute code (such as database updates) here.
// Redirect to this page.
header( "Location: {$_SERVER['REQUEST_URI']}", true, 303 );
exit();
}
Use REQUEST_URI
. Do not use PHP_SELF
as in most CMS systems and frameworks PHP_SELF
would refer to /index.php
.
I am confused about PHP Post/Redirect/Get
However, couldn't a user just navigate to the URL above?
Yes, he can. This will not cause anything bad though.
Also, what is the purpose of the GET variable?
To have some flag that represents the fact that the form has been processed successfully and you need to congratulate user.
Couldn't I just have a script at form.php that checks if the user is logged in?
Uhm, you can keep your code in the way you like. There is no any strong requirements
At submit.php, should I save the logged in username as $_SESSION['username'], and then check if isset() at form.php?
If you need to persist it across the current session - yes, do so.
Also, since a URL with "success" in it isn't really pretty, is it economical to redirect the user once again?
Redirect where. Redirection is pretty cheap thing.
Should I use PHP header() or Javascript window.location.href?
You definitely should do that in php, otherwise you'll get the troubles you're trying to avoid following PRG-way.
Understanding the post/redirect/get pattern
As you may know from your research, POST
-redirect-GET
looks like this:
- The client gets a page with a form.
- The form
POST
s to the server. - The server performs the action, and then redirects to another page.
- The client follows the redirect.
For example, say we have this structure of the website:
/posts
(shows a list of posts and a link to "add post")/<id>
(view a particular post)/create
(if requested with theGET
method, returns a form posting to itself; if it's aPOST
request, creates the post and redirects to the/<id>
endpoint)
/posts
itself isn't really relevant to this particular pattern, so I'll leave it out.
/posts/<id>
might be implemented like this:
- Find the post with that ID in the database.
- Render a template with the content of that post.
/posts/create
might be implemented like this:
- If the request is a
GET
request:- Show an empty form with the target set to itself and the method set to
POST
.
- Show an empty form with the target set to itself and the method set to
- If the request is a
POST
request:- Validate the fields.
- If there are invalid fields, show the form again with errors indicated.
- Otherwise, if all fields are valid:
- Add the post to the database.
- Redirect to
/posts/<id>
(where<id>
is returned from the call to the database)
PHP Redirect with POST data
Generate a form on Page B with all the required data and action set to Page C and submit it with JavaScript on page load. Your data will be sent to Page C without much hassle to the user.
This is the only way to do it. A redirect is a 303 HTTP header that you can read up on http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html, but I'll quote some of it:
The response to the request can be
found under a different URI and SHOULD
be retrieved using a GET method on
that resource. This method exists
primarily to allow the output of a
POST-activated script to redirect the
user agent to a selected resource. The
new URI is not a substitute reference
for the originally requested resource.
The 303 response MUST NOT be cached,
but the response to the second
(redirected) request might be
cacheable.
The only way to achieve what you're doing is with a intermediate page that sends the user to Page C. Here's a small/simple snippet on how you can achieve that:
<form id="myForm" action="Page_C.php" method="post">
<?php
foreach ($_POST as $a => $b) {
echo '<input type="hidden" name="'.htmlentities($a).'" value="'.htmlentities($b).'">';
}
?>
</form>
<script type="text/javascript">
document.getElementById('myForm').submit();
</script>
You should also have a simple "confirm" form inside a noscript tag to make sure users without Javascript will be able to use your service.
PHP - Redirect and send data via POST
You can't do this using PHP.
As others have said, you could use cURL - but then the PHP code becomes the client rather than the browser.
If you must use POST, then the only way to do it would be to generate the populated form using PHP and use the window.onload hook to call javascript to submit the form.
How to keep POST method's input values with post/redirect/get?
You need to transport those values via GET.
There are two options to do that:
- sessions
- URL query parameters
If you simply save the data in the session, you can read it from there and re-populate the form. If you put it into the URL, you can read it from there; but obviously the URL will contain a lot of data then.
Reading it from a session the data will not be unique to the specific page/redirect, but anyway you open that page again within the same session will show the same data. Passing the data via the URL will make it unique to the specific request.
As a middle ground, you can save the data in the session tied to a specific random id, redirect with this id in the URL (e.g. example.com/foo.php?i=12345
), the re-populate the data from the session with the specific id.
POST REDIRECT GET in form that submits to itself duplicate entries in database
Below is sample code if you want try.
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
Name: <input type="text" name="name">
Email: <input type="text" name="email">
Password: <input type="password" name="password">
<input type="submit" value="submit" name="send">
</form>
PHP Code and common.php is database connection file
<?php
require_once "common.php";
if(isset($_REQUEST['send']))
{
$name = $_POST['name'];
$email = $_POST['email'];
$password = $_POST['password'];
$check = "SELECT * FROM user WHERE name = '".$name."' AND email = '".$email."' AND password = '".$password."'";
$check_result = mysql_query($check) or die(mysql_error());
if(mysql_num_rows($check_result) > 0)
{
header('Location : post.php');
}
else
{
$sql = "INSERT INTO user (name,email,password) VALUES ('$name','$email','$password')";
$result = mysql_query($sql) or die(mysql_error());
}
}
?>
post/redirect/get
The request alone isn't a problem, especially that the alternative gives a pretty bad user experience.
However, when using a site with load balancing and/or database replication, you need to take care to ensure that the GET after POST will see the data that has been posted.
When using load balancing and caching, this is sometimes solved with "sticky sessions" that direct the same user to the same machine, so data stored in a write-through cache on that machine will be current.
When using database replication, GET requests after POST may need to read directly from the "primary" database, instead of a local "secondary" as usual.
Related Topics
"Connect Failed: Access Denied For User 'Root'@'Localhost' (Using Password: Yes)" from PHP Function
Sorting an Associative Array in PHP
How to Convert a Number to a Word in PHP
How to Properly Url Encode a String in PHP
How to Do This in Laravel, Subquery Where In
Woocommerce Action Hooks and Overriding Templates
How to Get the File Extension in PHP
PHP Fatal Error: Cannot Redeclare Class
Get PHP to Stop Replacing '.' Characters in $_Get or $_Post Arrays
Get the Last Inserted Id Using Laravel Eloquent
How to Increase the Execution Timeout in PHP
MySQL Prepared Statements With a Variable Size Variable List
Json_Decode Returns Null After Webservice Call
How to Check If a Date Is in a Given Range