PHP – Redirecting a form with POST variables

On more than one occasion, I’ve come across novice PHP developers looking for ways to redirect the user and his/her submitted form variables to another external website. More often than not, they’ll ask if they can somehow attach POST variables to a header redirect. After this fails and they finally realize that another solution is needed, they’ll sometimes attempt to use a library such asĀ cURL.

Wait… Hold up!

If this site has an API that you can access, then you should definitely use it instead of messing around with redirects. If they do have an API, then you should be able to interact with it using cURL. The solutions below are for websites that willingly accept POST data from users that are entering their site for the first time (PayPal and some of the other online merchants, for example). If the site does not officially accommodate such requests and you’re simply trying to glue all of this functionality together, then don’t be surprised to find out that your application breaks overnight because the site in question decides to rename a form field or add a captcha. NOTE: If the site currently requires a captcha before the form submission is accepted, then you’re out of luck as that is a completely different issue that is not covered here.

cURL

In this particular scenario, the problem with cURL is that the request is sent via the server. i.e. The request will not come from the user’s browser. Therefore, the user’s browser and the external website will be completely oblivious to one another. As far as they’re concerned, they’ve never even met each other before. This is because cURL is acting like a middleman between the user and the external website. It grabs the data from the user before forwarding it on. To put it bluntly: This means that if you forward the POST data via cURL, the website in question will fail to recognize your user as the person who originally submitted the form.

This can be a major issue if your user needs to carry out further actions after the form is submitted. For example, if the user needs to enter their credit card details or click on a confirmation button, then using cURL is going to be cumbersome at best. If the site relies on JavaScript or some other form of client-side processing, then using cURL is going to become even more complicated as cURL cannot process JavaScript or interact with Java applets and other browser plugins.

I don’t really care about redirecting the user. I just want to forward the POST data.

If you’re OK with not redirecting the user to the website in question, then a once-off cURL request might be the perfect solution for you. If the site accepts and accommodates POST requests without forcing the user to jump through hoops, then you could forward the data on like so:

<?php

//The names of the POST variables that we want to send
//to the external website.
$postVars = array('name', 'email', 'dob');

//An array to hold the data that we'll end up sending. 
//Empty by default.
$postData = array();

//Attemp to find the POST variables that we want to send.
foreach($postVars as $name){
    if(isset($_POST[$name])){
        $postData[$name] = $_POST[$name];
    }
}

//Setup cURL
$ch = curl_init();

//The site we'll be sending the POST data to.
curl_setopt($ch, CURLOPT_URL, "http://example.com");

//Tell cURL that we want to send a POST request.
curl_setopt($ch, CURLOPT_POST, 1);

//Attach our POST data.
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);

//Tell cURL that we want to receive the response that the site
//gives us after it receives our request.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

//Finally, send the request.
$response = curl_exec($ch);

//Close the cURL session
curl_close($ch);

//Do whatever you want to do with the output.
echo $response;

You could then parse the $response variable and inform the user that he/she was successful or not.

No. I need to make sure that the user is redirected.

In a lot of cases, you will need to redirect the user to the site in question. With online merchants such as PayPal, this is a must as the user will be prompted to enter their payment details once they’ve landed on the site. If you don’t need to process the form data before it is sent, then simply adding the external site’s URL to your form’s action attribute should be good enough:

<form action="http://example.com" method="post">
    <input type="text" name="name">
    <input type="text" name="email">
    <input type="text" name="etc">
    <input type="submit" name="submission_button">
</form>

The benefit of this is that you don’t even need to redirect the user. He or she just submits the form and the data goes directly to the site that is waiting to accept it.

But… I need to process the form data before the user leaves…

If you need to process the form data before the user leaves your website, then you will need to take the following steps:

  1. Process the user’s form submission.
  2. Bring the user to another page that has an “invisible form”. This “invisible form” should be created using hidden fields that contain data from the form that he/she previously submitted.
  3. Automatically submit the “invisible form” using JavaScript or simply prompt the user to submit it again by asking them to confirm their details.

The “invisible form” can look something like:

<form id="my_form" action="http://example.com" method="post">
    <input type="hidden" name="name" value="<?php echo htmlspecialchars($name); ?>">
    <input type="hidden" name="email" value="<?php echo htmlspecialchars($email); ?>">
    <input type="hidden" name="etc" value="<?php echo htmlspecialchars($etc); ?>">
</form>

<script type="text/javascript">
    //Our form submission function.
    function submitForm() {
        document.getElementById('my_form').submit();
    }
    //Call the function submitForm() as soon as the page has loaded.
    window.onload = submitForm;
</script>

The problem with the code above is that the user needs to have JavaScript enabled for it to work. As a fail-safe, you could add a visible submit button to the form. One that says something such as “Click here if the site is taking too long to redirect!” or “Confirm Submission”:

<?php
$name = isset($_POST['name']) ? $_POST['name'] : null;
$email = isset($_POST['email']) ? $_POST['email'] : null;
$etc = isset($_POST['etc']) ? $_POST['etc'] : null;
?>

<form id="my_form" action="http://example.com" method="post">
    <input type="hidden" name="name" value="<?php echo htmlspecialchars($name); ?>">
    <input type="hidden" name="email" value="<?php echo htmlspecialchars($email); ?>">
    <input type="hidden" name="etc" value="<?php echo htmlspecialchars($etc); ?>">
    <input type="submit" name="submission_button" value="Click here if the site is taking too long to redirect!">
</form>

<script type="text/javascript">
    function submitForm() {
        document.getElementById('my_form').submit();
    }
    window.onload = submitForm;
</script>