PHP表单:服务器响应状态为400(错误请求)

时间:2018-06-27 20:14:49

标签: javascript php

这可能是很多代码,对不起。我现在要离开工作,所以如果有人有解决方案,或者可以在本地运行该解决方案并为我提供帮助,那我可能不会立即答复。

我以前从未使用后端PHP(我通常只是前端)来完成其中一种表单提交。我收到此400错误的请求错误,我不确定该怎么做。我将PHP与代码段分开放置,因为在代码段中没有可以播放PHP代码的地方。

我的目录结构是这样:

public(root):
 -(inside public) assets/js/mailer.js
 -(inside public) mailer.php

$(document).ready(function() {
  $("#submit").on('click', function() {
    var name = $("#name").val();
    var email = $("#email").val();
    var phone = $("#phone").val();
    var institution = $('#institution').val();
    var message = $("#message").val();

    $("#returnmessage").empty(); // To empty previous error/success message.
    // Checking for blank fields.
    if (name == '' || email == '' || phone == '' || institution == '' || message == '') {
      alert("Please Fill Required Fields");
    } else {
      // Returns successful data submission message when the entered information is stored in database.
      $.post("../../mailer.php", {
          name1: name,
          email1: email,
          institution1: institution,
          contact1: phone,
          message1: message
        },
        function(data) {
          $("#returnmessage").append(data); // Append returned message to message paragraph.

          if (data == "Your message was received. We will contact you shortly.") {
            $("#ajax-contact")[0].reset(); // To reset form fields on success.
          }
        });
    }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="ajax-contact" method="post" action="mailer.php" class="mu-contact-form">
  <div class="row">
    <div class="col-lg-6 input-field-name form-group">
      <input type="text" class="form-control scroll-left" placeholder="Name" id="name" name="name" required>
    </div>
    <div class="col-lg-6 input-field-email form-group">
      <input type="text" class="form-control scroll-right" placeholder="Email" id="email" name="email" required>
    </div>
  </div>
  <div class="form-group">
    <input type="tel" class="form-control scroll-bottom" placeholder="Phone" id="phone" name="phone" required>
  </div>
  <div class="form-group">
    <input type="text" class="form-control scroll-bottom" placeholder="Institution / Organization" id="institution" name="institution" required>
  </div>
  <div class="form-group">
    <textarea class="form-control scroll-bottom" placeholder="Message" id="message" name="message" required></textarea>
  </div>
  <p id="returnmessage"></p>
  <input type="button" id="submit" class="submit scroll-top"><span>Submit</span></input>
</form>

以下是PHP:

<?php
    // My modifications to mailer script from:
    // http://blog.teamtreehouse.com/create-ajax-contact-form
    // Added input sanitizing to prevent injection

    // Only process POST reqeusts.
    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);

        $institution = trim($_POST["institution"]);
        $phone = trim($_POST["phone"]);


        $email = filter_var(trim($_POST["email"]), FILTER_SANITIZE_EMAIL);
        // $cont_subject = trim($_POST["subject"]);
        $message = trim($_POST["message"]);

        $required = "This field is required"; 

        // Check that data was sent to the mailer.
        if ( empty($name) OR empty($institution) 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);
            echo $required;
            exit;
        }

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

        // Set the email subject.
        $subject = "New message from: $name ($email)";

        // Build the email content.
        $email_content = "Name: $name\n";
        $email_content .= "Institution: $institution\n";
        $email_content .= "Email: $email\n";
        $email_content .= "Phone: $phone\n\n";
        $email_content .= "Message:\n$message";

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

        // Send the email.
        if (mail($recipient, $subject, $email_content, $email_headers)) {
            echo "Thank You! Your message has been sent.";
        } else {
            echo "Something went wrong and we couldn't send your message.";
        }
    } 
    else {
            echo "There was a problem with your submission, please try again.";
    }

?>

1 个答案:

答案 0 :(得分:2)

我测试了您的代码-参见下文。那里有一些问题,我将在评论中进行详细描述。只需搜索@todo@see@link

我故意清空变量$recipient,并在“ mailer.php”末尾注释了邮件发送部分。因此,填写$recipient的值,然后取消注释邮件发送部分,以便进行测试。

我试图只更改必要的代码部分。

P.S: headers 主题乍一看并不容易。因此,随时向我提问,我会尽力在SO聊天中向您解释。

public / index.php:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo</title>

        <!-- CSS assets -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
        <link rel="stylesheet" href="assets/css/mailer.css">

        <!-- JS assets -->
        <!-- @todo Loaded needed js resources and mailer.js -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
        <script src="assets/js/mailer.js"></script>
    </head>
    <body>

        <!-- @todo Added container. -->
        <div class="container">

            <!-- @todo Added header. -->
            <header>
                <h2>
                    Demo
                </h2>
            </header>

            <form id="ajax-contact" method="post" action="mailer.php" class="mu-contact-form">
                <div class="row">
                    <div class="col-lg-6 input-field-name form-group">
                        <input type="text" class="form-control scroll-left" placeholder="Name" id="name" name="name" required>
                    </div>
                    <div class="col-lg-6 input-field-email form-group">
                        <input type="text" class="form-control scroll-right" placeholder="Email" id="email" name="email" required>
                    </div>
                </div>

                <div class="form-group">
                    <input type="tel" class="form-control scroll-bottom" placeholder="Phone" id="phone" name="phone" required>
                </div>

                <div class="form-group">
                    <input type="text" class="form-control scroll-bottom" placeholder="Institution / Organization" id="institution" name="institution" required>
                </div>

                <div class="form-group">
                    <textarea class="form-control scroll-bottom" placeholder="Message" id="message" name="message" required></textarea>
                </div>

                <p id="returnmessage"></p>

                <!-- @todo Changed button bec. the "input" code was wrong - it didn't fire the onclick event. -->
                <button type="button" id="submit" class="btn btn-success">
                    <span>Submit</span>
                </button>
            </form>

        </div>
    </body>
</html>

public / assets / js / mailer.js:

$(document).ready(function () {
    $("#submit").on('click', function () {
        var name = $("#name").val();
        var email = $("#email").val();
        var phone = $("#phone").val();
        var institution = $('#institution').val();
        var message = $("#message").val();

        $("#returnmessage").empty(); // To empty previous error/success message.

        // Checking for blank fields.
        if (name == '' || email == '' || phone == '' || institution == '' || message == '') {
            alert("Please Fill Required Fields");
        } else {
            // Returns successful data submission message when the entered information is stored in database.
            /*
             * @todo Changed the path to "mailer.php" because the path must be relative
             * to the including page (here "index.php"), not to the included file (here "mailer.js").
             * @todo Changed "name1" to "name", etc, because see mailer.php @todos.
             * @todo Added the "fail" callback. Why? Because:
             * The page "mailer.php" throws a 420 (earlier 400) response header (from the "if" statement),
             * which is read by the browser and, based on its code (420), recognized as an error. So,
             * the browser activates the "fail" callback.
             * From the jQuery website: "If a request with jQuery.post() returns an error code,
             * it will fail silently". So you must define a "fail" callback to handle the eventual errors.
             *
             * Note that, if the status code of the response is a custom one (420), defined by
             * the developer, then the corresponding error message is to be displayed.
             * Otherwise, e.g. if a system error occurres, the displayed message must
             * be a general, user-friendly one. So that no system-related infos will be shown to any user!
             *
             * Try to toggle between 420 and 400 in "mailer.php", in order to
             * see which error message is displayed in the "fail" callback.
             *
             * @link https://api.jquery.com/jQuery.post/ jQuery.post().
             * @link https://api.jquery.com/jQuery.ajax/ jQuery.ajax().
             */
            $.post("mailer.php", {
                name: name,
                email: email,
                institution: institution,
                contact: phone,
                message: message
            }, function (data) {
                //@todo Added this line. It adds a "success" class to the "returnmessage" container.
                $("#returnmessage").removeClass('error').addClass('success');

                $("#returnmessage").append(data); // Append returned message to message paragraph.

                $("#ajax-contact")[0].reset(); // To reset form fields on success.
            }).fail(function (jqXHR, textStatus, errorThrown) {
                var message;

                if (jqXHR.status === 420) {
                    // The status code of the response is a custom one (420).
                    message = jqXHR.statusText;
                } else {
                    /*
                     * A system error occurred. E.g. the status code of the response is set by
                     * the system. For example a 400 code (described with the text "Bad Request").
                     */
                    message = 'An error occurred during your request. Please try again, or contact us.';
                }

                //@todo Added this line. It adds an "error" class to the "returnmessage" container.
                $("#returnmessage").removeClass('success').addClass('error');

                $("#returnmessage").append(message);
            });
        }
    });
});

public / assets / css / mailer.css:

#returnmessage.error {
    color: #c00;
}

#returnmessage.success {
    color: #3adb76;
}

public / mailer.php:

<?php

// My modifications to mailer script from:
// http://blog.teamtreehouse.com/create-ajax-contact-form
// Added input sanitizing to prevent injection
// Only process POST reqeusts.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    /*
     * @todo This part activated a "400 bad Request" error because, for example,
     * you've sent "name1" from ajax, but here you are referencing the "name".
     * @see The comment marked with [*] bellow.
     */
    // Get the form fields and remove whitespace.
    $name = strip_tags(trim($_POST["name"]));
    $name = str_replace(array("\r", "\n"), array(" ", " "), $name);

    $institution = trim($_POST["institution"]);

    //@todo Changed from "phone" to "contact", because "contact" were posted, not "phone".
    $phone = trim($_POST["contact"]);

    $email = filter_var(trim($_POST["email"]), FILTER_SANITIZE_EMAIL);

    // $cont_subject = trim($_POST["subject"]);
    $message = trim($_POST["message"]);

    // Check that data was sent to the mailer.
    /*
     * @todo Try to use the logical operator "||" instead of "OR", "&&" instead of "AND", etc.
     * @link https://secure.php.net/manual/en/language.operators.logical.php Logical Operators.
     */
    if (
            empty($name) ||
            empty($institution) ||
            empty($phone) ||
            empty($message) ||
            !filter_var($email, FILTER_VALIDATE_EMAIL)
    ) {
        /*
         * @todo
         *
         * [*] This code triggered the 400 header because
         * the values posted by ajax were undefined.
         *
         * I changed to "header(...)" instead of "http_response_code(...)" + "echo ...".
         *
         * I changed 400 to 420 because 400 is a code
         * reserved by the system. See the rule bellow:
         *
         * This custom response header triggers the ajax error (see the "fail" callback in the js file)
         * because the status code begins with 4xx (which corresponds to the "client errors"). Here is
         * defined "420" as the custom status code. One can choose whatever code between 401-499 which
         * is not officially assigned, e.g. which is marked as "Unassigned" in the official
         * HTTP Status Code Registry. See the link.
         *
         * @link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml HTTP Status Code Registry.
         */
        // Send a 420 custom response header (to the browser) and exit.
        header('HTTP/1.1 420 This field is required');
        exit();
    }

    // Set the recipient email address.
    // FIXME: Update this to your desired email address.
    /*
     * @todo Don't post sensible info on public websites!
     * I deleted the email address. Fill it on your system.
     */
    $recipient = "";

    // Set the email subject.
    $subject = "New message from: $name ($email)";

    // Build the email content.
    $email_content = "Name: $name\n";
    $email_content .= "Institution: $institution\n";
    $email_content .= "Email: $email\n";
    $email_content .= "Phone: $phone\n\n";
    $email_content .= "Message:\n$message";

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

    // Send the email.
    //@todo Uncomment only after assigning an email address to the "$recipient" variable.
    // $mailSent = mail($recipient, $subject, $email_content, $email_headers);

    /*
     * @todo You can toggle between TRUE and FALSE to test, then delete
     * this line after activating the line "$mailSent = ..." above.
     */
    $mailSent = TRUE;

    if ($mailSent) {
        echo "Thank You! Your message has been sent.";
    } else {
        /*
         * @todo Here too: Throw a custom response header instead of just printing a text.
         * This way the header will be treated as error by the browser, which will manage
         * it with the "fail" callback of the ajax request.
         */
        // Send a 420 custom response header (to the browser) and exit.
        header('HTTP/1.1 420 Something went wrong and we could not send your message.');
        exit();
    }
} else {
    /*
     * @todo Here too: Throw a custom response header instead of just printing a text.
     * This way the header will be treated as error by the browser, which will manage
     * it with the "fail" callback of the ajax request.
     */
    // Send a 420 custom response header (to the browser) and exit.
    header('HTTP/1.1 420 There was a problem with your submission. Please try again.');
    exit();
}