56

I'm working with PHP, and I'm making an action page which a form posts to. The page checks for errors, then if everything is fine, it redirects them to the page where the data has been posted. If not, I need to to redirect them back to the page they were at with an error and the POST variables. Here is the gist of how it works.

The HTML would look like this...

<form name="example" action="action.php" method="POST">
  <input type="text" name="one">
  <input type="text" name="two">
  <input type="text" name="three">
  <input type="submit" value="Submit!">
</form>

action.php would look like this...

if(error_check($_POST['one']) == true){
    header('Location: form.php');
    // Here is where I need the data to POST back to the form page.
} else {
    // function to insert data into database
    header('Location: posted.php');
}

In the case of an error, I need it to POST back to the first page. I can't use GET, because the input will be too large. I don't want to use SESSION, if possible. Is this possible?

ashkufaraz
  • 5,179
  • 6
  • 51
  • 82
Yoshiyahu
  • 2,089
  • 7
  • 22
  • 34
  • According to some thread at http://www.phpfreaks.com/forums/php-coding-help/header('location-x-php')-question-going-2-pages-back/, you may be able to use `header("Location: javascript:window.history.go(-1);");` (not tested) – cambraca Nov 26 '10 at 01:12
  • Well... I was also hoping to try adding an error message if I needed to. That wouldn't allow that. – Yoshiyahu Nov 26 '10 at 01:15

5 Answers5

30
// from http://wezfurlong.org/blog/2006/nov/http-post-from-php-without-curl
function do_post_request($url, $data, $optional_headers = null)
{
  $params = array('http' => array(
              'method' => 'POST',
              'content' => $data
            ));
  if ($optional_headers !== null) {
    $params['http']['header'] = $optional_headers;
  }
  $ctx = stream_context_create($params);
  $fp = @fopen($url, 'rb', false, $ctx);
  if (!$fp) {
    throw new Exception("Problem with $url, $php_errormsg");
  }
  $response = @stream_get_contents($fp);
  if ($response === false) {
    throw new Exception("Problem reading data from $url, $php_errormsg");
  }
  return $response;
}
bowsersenior
  • 12,524
  • 2
  • 46
  • 52
20

If you don't want to use sessions, the only thing you can do is POST to the same page. Which IMO is the best solution anyway.

// form.php

<?php

    if (!empty($_POST['submit'])) {
        // validate

        if ($allGood) {
            // put data into database or whatever needs to be done

            header('Location: nextpage.php');
            exit;
        }
    }

?>

<form action="form.php">
    <input name="foo" value="<?php if (!empty($_POST['foo'])) echo htmlentities($_POST['foo']); ?>">
    ...
</form>

This can be made more elegant, but you get the idea...

deceze
  • 510,633
  • 85
  • 743
  • 889
  • That is currently what I have been doing, but I'm trying to make my server actions on different pages for tidyness... – Yoshiyahu Nov 26 '10 at 01:21
  • just curious, will the POST data be available on nextpage.php? – jerjer Nov 26 '10 at 01:21
  • @jerjer No, that's the point why you either need to do all processing on the same page or use sessions to persist data between pages. – deceze Nov 26 '10 at 01:23
  • 5
    @Yoshi You could simply split the files and `include` the HTML form when necessary. – deceze Nov 26 '10 at 01:23
  • That may be the best idea I've heard yet. – Yoshiyahu Nov 26 '10 at 01:26
  • I'll just use it on the same page, I suppose. – Yoshiyahu Nov 26 '10 at 01:35
  • @deceze, thanks! that i should note!t :) – jerjer Nov 26 '10 at 01:37
  • Using the same page is probably better, as it encapsulates all the functionality without duplicating any testing, as any target page beyond the original testing one may be visited directly, so it would need to validate essential values. Or, use header('HTTP/1/1 307 Temporary Redirect'); before the header('Location: ...');. – Patanjali Jun 04 '16 at 07:18
8

It is not possible to redirect a POST somewhere else. When you have POSTED the request, the browser will get a response from the server and then the POST is done. Everything after that is a new request. When you specify a location header in there the browser will always use the GET method to fetch the next page.

You could use some Ajax to submit the form in background. That way your form values stay intact. If the server accepts, you can still redirect to some other page. If the server does not accept, then you can display an error message, let the user correct the input and send it again.

Jan Thomä
  • 13,296
  • 6
  • 55
  • 83
  • Great idea, and you answered my question. However, I'm shying away from Javascript on this project. – Yoshiyahu Nov 26 '10 at 01:27
  • 3
    Not so. header('HTTP/1.1 307 Temporary Redirect') and header('HTTP/1.1 308 Permanent Redirect') maintain the original method to redirect using a following header('Location: new_url'). – Patanjali Jun 04 '16 at 07:00
  • You realize that this answer was from 2010 when these status codes were non-existent or at least largely unsupported. If you have the knowledge about this you could post up a full answer showing how to utilize these new status codes to solve the OP's issue. I think many people would find this useful. – Jan Thomä Jun 06 '16 at 12:04
  • 2
    @JanThomä. Lapsed time is irrelevant if an issue is still valid for new people to need help on. I only just came back to this page when researching the issue again. I could not provide an answer here, but I did provide a sample full php PayPal payment page in: http://stackoverflow.com/questions/2865289/php-redirection-with-post-parameters#answer-39158782 – Patanjali Aug 26 '16 at 05:32
0

It would be beneficial to verify the form's data before sending it via POST. You should create a JavaScript function to check the form for errors and then send the form. This would prevent the data from being sent over and over again, possibly slowing the browser and using transfer volume on the server.

Edit:

If security is a concern, performing an AJAX request to verify the data would be the best way. The response from the AJAX request would determine whether the form should be submitted.

Evan Mulawski
  • 54,662
  • 15
  • 117
  • 144
  • 1
    You should still check the data on the server otherwise you might end up with a security issue. – Jan Thomä Nov 26 '10 at 01:16
  • Exactly what I was thinking, kork. Server side error checking is always best. – Yoshiyahu Nov 26 '10 at 01:18
  • There are always security issues, no matter how you verify data. If security is a concern, an AJAX request for verification may be the way to go. – Evan Mulawski Nov 26 '10 at 01:18
  • @Evan How is this any more secure? You will still need to validate the data after it's been posted, no way around it. – deceze Nov 26 '10 at 01:20
  • An AJAX request to execute a PHP script that verifies the data is more secure than just using JavaScript. – Evan Mulawski Nov 26 '10 at 01:22
  • I'm not in favor of javascript for any type of security. Why? I'm a Greasemonkey scripter. – Yoshiyahu Nov 26 '10 at 01:22
  • @Evan If you POST the data to the server using AJAX and the server uses this data to put into the database or whatever, that's alright. But it's not any different from a normal POST. If you send the data to the server via AJAX, the server validates it, sends back a message "this is valid/invalid", then you send the data again via a normal POST, that'd be totally pointless and not any more secure than local Javascript validation. – deceze Nov 26 '10 at 01:43
  • Technically, validating data using PHP is more secure than using local JavaScript. Local JavaScript can be modified using a DOM inspector. Modifying a remote PHP script is impossible. – Evan Mulawski Nov 26 '10 at 01:52
  • @Evan So... Why is Javascript that asks the server any more secure then? If I just disable the whole AJAX call and just `return true`, the form validates without having been validated. The data needs to be validated right before it goes into the database (or whatever), full stop. Making a round trip through the client is not trustworthy however you do it. – deceze Nov 26 '10 at 02:31
  • Very true. Most sites today use some sort of AJAX verification, however. There is an extremely limited amount of ways to validate data securely. We either risk using JavaScript or subject to SQL injection. Nothing is ever 100% secure. – Evan Mulawski Nov 26 '10 at 02:41
  • 2
    @Evan Huh...? SQL injections are no problem if you're doing it right. Validations are also no problem if you **validate the data you are going to use on the server.** I.e. POST -> validation -> SQL injection safe data handling -> return response to client. Those are the basics you have to stick to, always. If you're going to use Javascript at all in this process, it's completely secondary and optional and only there to provide a little more interactivity, it's not your first, second or any line of defense against malicious attackers. – deceze Nov 26 '10 at 02:56
  • lol, just checked this out. First off, in the end, I would wind up using JavaScript + PHP. Why not just use PHP? – Yoshiyahu Dec 04 '10 at 03:22
0

Use a smarty template for your stuff then just set the POST array as a smarty array and open the template. In the template just echo out the array so if it passes:

if(correct){
    header("Location: passed.php");
} else {
    $smarty->assign("variables", $_POST);
    $smarty->display("register_error.php");
    exit;
}

I have not tried this yet but I am going to try it as a solution and will let you know what I find. But of course this method assumes that you are using smarty.

If not you can just recreate your form there on the error page and echo info into the form or you could send back non important data in a get from and get it

ex.

register.php?name=mr_jones&address==......
echo $_GET[name];
LoveAndCoding
  • 7,857
  • 2
  • 31
  • 55
Derrick
  • 11