24

I have made a contact form based on this tutorial: http://blog.teamtreehouse.com/create-ajax-contact-form

I'm using PHP Version 5.3.10-1ubuntu3.4 on my server and I've been having trouble with http_response_code(); which is what the example tutorial at the above link uses. I've read http_response_code(); only works with PHP 5.4. So instead I have reverted to using header();.

I have my form working just fine and it's displaying a success message when I submit, rather than errors when I was using http_response_code(); but my PHP isn't that great and I am wanting to know if what I have done is acceptable or if I should be doing it a different way? Please correct my code if so.

Here's the contents of my mailer.php file, where you can see I've commented out http_response_code(); and am using header();.

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Get the form fields and remove whitespace.
    $name = strip_tags(trim($_POST["name"]));
    $name = str_replace(array("\r","\n"),array(" "," "),$name);
    $email = filter_var(trim($_POST["email"]), FILTER_SANITIZE_EMAIL);
    $phone = trim($_POST["phone"]);
    $company = trim($_POST["company"]);
    $minbudget = trim($_POST["minbudget"]);
    $maxbudget = trim($_POST["maxbudget"]);
    $message = trim($_POST["message"]);
    $deadline = trim($_POST["deadline"]);
    $referred = trim($_POST["referred"]);

    // Check that data was sent to the mailer.
    if ( empty($name) OR empty($phone) OR empty($message) OR !filter_var($email, FILTER_VALIDATE_EMAIL)) {
        // Set a 400 (bad request) response code and exit.
        //http_response_code(400);
        header("HTTP/1.1 400 Bad Request");
        echo "Error (400). That's not good, refresh and try again otherwise please email me and let me know you are having trouble submitting this form.";
        exit;
    }

    // Set the recipient email address.
    // FIXME: Update this to your desired email address.
    $recipient = "myemail@domain.com";

    // Set the email subject.
    $subject = "Website enquiry from $name";

    // Build the email content.
    $email_content = "Name: $name\n";
    $email_content .= "Email: $email\n\n";
    $email_content .= "Phone: $phone\n";
    $email_content .= "Company: $company\n\n";

    $email_content .= "Budget: $minbudget $maxbudget\n";
    $email_content .= "Deadline: $deadline\n";
    //$email_content .= "Max Budget: $maxbudget\n";

    $email_content .= "\n$message\n\n";        

    $email_content .= "Referred: $referred\n";

    // Build the email headers.
    $email_headers = "From: $name <$email>";

    // Send the email.
    if (mail($recipient, $subject, $email_content, $email_headers)) {
        // Set a 200 (okay) response code.
        //http_response_code(200);
        header("HTTP/1.1 200 OK");
        echo "Thank You! I'll be in touch soon.";
    } else {
        // Set a 500 (internal server error) response code.
        //http_response_code(500);
        header("HTTP/1.0 500 Internal Server Error");
        echo "Error (500). That's not good, refresh and try again otherwise please email me and let me know you are having trouble submitting this form.";
    }

} else {
    // Not a POST request, set a 403 (forbidden) response code.
    //http_response_code(403);
    header("HTTP/1.1 403 Forbidden");
    echo "Error (403). That's not good, refresh and try again otherwise please email me and let me know you are having trouble submitting this form.";
}
sanmai
  • 29,083
  • 12
  • 64
  • 76
Glen
  • 271
  • 1
  • 2
  • 5
  • 3
    Please don't change the HTTP status codes unless you're actually using them correctly, 403 is being missused(it's supposed to indicate that you lack permission, not that you're submitting the request wrong, that's what 405 is for), and you shouldn't be submitting 400 errors unless the headers are actually corrupt(since 400 indicates an error parsing the headers, which there clearly isn't). – scragar Aug 14 '14 at 11:09
  • 1
    Your mail code has many problems - I suggest you use a library, such as [PHPMailer](https://github.com/PHPMailer/PHPMailer), since you tagged the question with that, but are not using it! – Synchro Aug 14 '14 at 11:45
  • 1
    @scragar - not true. Using 400's as a response to malformed/invalid data in json/api post, is fairly common place, and is further [supported by this popular thread on stackoverflow](http://stackoverflow.com/a/19671511/3504007) – Kraang Prime Dec 22 '16 at 22:15

3 Answers3

33

I've managed to answer this on my own similar question by going through the PHP source code to work out exactly what happens.

The two methods are essentially functionally equivalent. http_response_code is basically a shorthand way of writing a http status header, with the added bonus that PHP will work out a suitable Reason Phrase to provide by matching your response code to one of the values in an enumeration it maintains within php-src/main/http_status_codes.h.

Note that this means your response code must match a response code that PHP knows about. You can't create your own response codes using this method, however you can using the header method. Note also that http_response_code is only available in PHP 5.4.0 and higher.

In summary - The differences between http_response_code and header for setting response codes:

  1. Using http_response_code will cause PHP to match and apply a Reason Phrase from a list of Reason Phrases that are hard-coded into the PHP source code.

  2. Because of point 1 above, if you use http_response_code you must set a code that PHP knows about. You can't set your own custom code, however you can set a custom code (and Reason Phrase) if you use the header function.

  3. http_response_code is only available in PHP 5.4.0 and higher

Community
  • 1
  • 1
sg-
  • 2,196
  • 1
  • 15
  • 16
  • 1
    If `http_response_code(403);` is used somewhere in a script, should it be followed by `exit`? Or does further execution get terminated implicitly by `http_response_code(403);`? – W.M. Dec 22 '16 at 12:20
  • 5
    It doesn't terminate execution. So if you want to exit after setting the response code you'll have to explicitly exit. – sg- Dec 22 '16 at 20:50
  • @W.M. just imagine a 404 error page - you want to first set up the correct HTTP response, but then still show an error message using normal HTML code. Also this response should be accepted as the right one. – Kalko Dec 05 '19 at 14:09
7

Easy solution:

/**
 * Sets the response code and reason
 *
 * @param int    $code
 * @param string $reason
 */
function setResponseCode($code, $reason = null) {
    $code = intval($code);

    if (version_compare(phpversion(), '5.4', '>') && is_null($reason))
        http_response_code($code);
    else
        header(trim("HTTP/1.0 $code $reason"));

}

you can use it as:

setResponseCode(404);

or

setResponseCode(401,'Get back to the shadow');
biesior
  • 55,576
  • 10
  • 125
  • 182
  • Nice little wrapper method! In production, that `else` should already grab from a list of `$reason` values either hard-coded or from a language file with constants. – Kraang Prime Dec 22 '16 at 22:17
2

To answer your main question, the biggest response I could see to using headers vs http_response_code(), is that http_response_code() is only supported on PHP 5.4 and greater, older versions would fail using that function.

Using headers as you are in your example will insure you're code will work on older versions.

TroySteven
  • 4,885
  • 4
  • 32
  • 50