web 表单自定义字段_带有自定义服务器字段验证的AJAX表单提交

web 表单自定义字段

Overview

总览

This article presents a method for validating form data in a PHP script using custom server side validation rules. The example presented uses AJAX to submit data to the script but the same method can be used for normal form submissions. I have chosen to use AJAX as that makes the most sense for form processing. If the data in a form is not correct you want the user to stay on the page and correct the data. Round tripping to the server to validate and then re-render a page that was already perfectly rendered is wasteful, complicated and just plain unnecessary. With an AJAX request we pass the form data to the server and get back a list of errors. If no errors are returned the form is good - otherwise we display the errors, in this case, adjacent to the field that caused the error but you can put them wherever it suites you. 

本文介绍了一种使用自定义服务器端验证规则来验证PHP脚本中的表单数据的方法。 所提供的示例使用AJAX将数据提交到脚本,但是可以使用相同的方法来提交普通表单。 我选择使用AJAX,因为这对于表单处理最有意义。 如果表单中的数据不正确,则您希望用户停留在页面上并更正数据。 往返于服务器以进行验证,然后重新呈现已经完美呈现的页面是浪费,复杂且完全没有必要的。 通过AJAX请求,我们将表单数据传递到服务器,并获取错误列表。 如果未返回任何错误,则该表单是正确的-否则,在这种情况下,我们会在导致错误的字段旁边显示错误,但您可以将其放在适合您的位置。

Let's start with a basic Bootstrap form with three fields for First Name, Last Name and Email address. I have chosen Bootstrap as this is widely used framework that includes out-of-the-box styles for things like alerts in forms. It is not necessary to use Bootstrap - you can roll your own alerts according to your application requirements.

让我们从一个基本的Bootstrap表单开始,其中包含三个字段,分别是名字,姓氏和电子邮件地址。 我选择Bootstrap是因为它是一种广泛使用的框架,其中包括开箱即用的样式,用于表单中的警报。 不必使用Bootstrap-您可以根据应用程序要求滚动自己的警报。

The HTML

HTML

<form class="form" action="validate.php">
    <div class="row">
        <label for="firstname" class="col-md-3">First Name</label>
        <div class="col-md-9">
            <input type="text" name="firstname" id="firstname" class="form-control" />
        </div>
        <label for="lastname" class="col-md-3">Last Name</label>
        <div class="col-md-9">
            <input type="text" name="lastname" id="lastname" class="form-control" />
        </div>
        <label for="email" class="col-md-3">Email</label>
        <div class="col-md-9">
            <input type="text" name="email" id="email" class="form-control" />
        </div>
        <button class="pull-right btn btn-primary">Send</button>
    </div>
</form>

 

The AJAX

AJAX

The form is going to be submitted via AJAX - the following code will generically submit a form using AJAX. It retrieves the target from the action attributed of the form.

表单将通过AJAX提交-以下代码将通常使用AJAX提交表单。 它从表单的属性操作中检索目标。

<script>
$(function() {
    $('form').submit(function(e) {
        // PREVENT DEFAULT SUBMIT
        e.preventDefault();

        // GOOD PRACTICE
        var frm = this;
      
        var data = $(frm).serialize();
        var action = $(frm).attr('action');
        $.ajax({
            url: action,
            data: data,
            type: 'POST',
            dataType: 'JSON'
        }).done(function(resp) {
            if (resp.status) {
                $(frm).html(resp.message);
            }
            else {
                $('#response').html(resp.message);
            }
        });
    });
});
</script> 

What about client side validation? While not the subject of this article, client side validation is an important component in the user interaction process. It allows us to correct user errors before going back to the server. However, it is not a replacement for server side validation. The server must assume that all input is potentially harmful - it cannot assume that the client side validation was performed.

客户端验证呢? 尽管不是本文的主题,但客户端验证是用户交互过程中的重要组成部分。 它使我们能够在返回服务器之前纠正用户错误。 但是,它不能替代服务器端验证。 服务器必须假定所有输入都可能有害-它不能假定已执行客户端验证。

The PHP {validate.php}

PHP {validate.php}

On the server we could have something like this:

在服务器上,我们可能会遇到以下情况:

header('Content-Type: application/json');

That should give the basics of a generic AJAX form submission.

这应该提供通用AJAX表单提交的基础。

However, it is not as useful as it could be - we might want to validate multiple fields and see status messages for each of them.

但是,它并不是那么有用-我们可能想要验证多个字段并查看每个字段的状态消息。

To do that let's make some changes. Firstly, lets make the form names array references instead. The reason for this will be explained later.

为此,我们进行一些更改。 首先,让我们改为使用表单名称数组引用。 稍后将解释其原因。

HTML

HTML

<form class="form" action="validate.php">
    <div class="row">
        <label for="firstname" class="col-md-3">First Name</label>
        <div class="col-md-9">
            <input type="text" name="data[firstname]" id="firstname" class="form-control" />
        </div>
        <label for="lastname" class="col-md-3">Last Name</label>
        <div class="col-md-9">
            <input type="text" name="data[lastname]" id="lastname" class="form-control" />
        </div>
        <label for="email" class="col-md-3">Email</label>
        <div class="col-md-9">
            <input type="text" name="data[email]" id="email" class="form-control" />
        </div>
        <button class="pull-right btn btn-primary">Send</button>
    </div>
</form> 

On the server we can now access all of our form variables by accessing the data array. Because our variables are all in the data array we can easily retrieve the form-only variables from the post and pass them to our validation. You could simply pass the $_POST array to the validation function with the same result but if there happen to be other fields in the POST that you don't want in the outgoing email or database entry then this method allows you to isolate the variable you do want from any other control variables (CSRF, Captcha etc).

现在,在服务器上,我们可以通过访问数据数组来访问所有表单变量。 因为我们的变量都在数据数组中,所以我们可以轻松地从帖子中检索仅表单的变量,并将其传递给我们的验证。 您可以简单地将$ _POST数组传递给验证函数,并获得相同的结果,但如果POST中碰巧不希望在外发电子邮件或数据库条目中使用其他字段,则此方法可让您隔离变量确实需要其他控制变量(CSRF,验证码等)。

PHP

PHP

<?php
$data = isset($_POST['data']) ? $_POST['data'] : false;
if ($data &amp;&amp; is_array($data) {
  // we have valid form input
} 

To validate each field lets define an array that contains the field names as keys each pointing to a sub-array. 

为了验证每个字段,让我们定义一个包含字段名称的数组作为每个指向子数组的键。

Each sub-array has at least a message and optionally other parameters that determine how the field must be validated. The array below uses three different validation methods

每个子数组至少具有一条消息以及可选的其他参数,这些参数确定必须如何验证字段。 下面的数组使用三种不同的验证方法

  • Check for existence only and optionally a length

    仅检查是否存在,并检查长度
  • Use a regex pattern to verify validity

    使用正则表达式模式验证有效性
  • Specifically validate an email address

    具体验证电子邮件地址
$validate = array (
    'firstname' => array('msg' => 'Please enter a valid first name', 'type' => 'exist', 'length' => 3),
    'lastname' => array('msg' => 'Please enter a valid last name', 'type' => 'regex', 'pattern' => '/^[a-zA-Z\-]{3,}$/'),
    'email' => array('msg' => 'Please enter a valid email address', 'type' => 'email')
);

 

Note: I have used different rules for firstname and lastname so that I can illustrate how different fields can have different validation rules - in reality these two fields would probably share the same rule.

注意:我对名字和姓氏使用了不同的规则,以便说明不同的字段如何具有不同的验证规则-实际上,这两个字段可能共享相同的规则。

Validation vs Sanitation

验证与卫生

A short sidebar on Validation vs Sanitation. Validating data is making sure incoming input matches the rules for data required by your business logic / model. We to see that the correct data has been retrieved for each field. 

关于验证与卫生的简短补充说明。 验证数据可确保输入符合业务逻辑/模型所需数据的规则。 我们看到已经为每个字段检索了正确的数据。

Sanitation is the removal of any potential malicious data from the submission. While there is often overlap between these two necessary server side processes - they are distinctly different. In this article we are specifically looking at validation.

卫生措施是从提交中删除任何潜在的恶意数据。 虽然这两个必要的服务器端过程之间经常有重叠,但是它们却截然不同。 在本文中,我们专门研究验证。

Let's define how each of these validation options will be processed.

让我们定义如何处理每个验证选项。

<?php
//...
// CODE TO MANAGE CLIENT INTERACTION LEFT OUT FOR THIS SNIPPET
// ...
// THE VALIDATION CONTROL FUNCTION. TAKES AN ARRAY OF DATA 
// EXTRACTED FROM THE $_POST AND A VALIDATION ARRAY AGAINST WHICH
// TO VALIDATE THE EXTRACTED DATA
function validate($data, $validation)
{
    // WE ONLY NEED TO CHECK THE VALIDATION ARRAY AND THEN USE
    // KEYS TO SEE IF THE VALUE EXISTS IN THE DATA ARRAY

    // OUR RETURN ARRAY - ASSUME THE BEST
    $error = array();

    // CHECK EACH VALIDATION ENTRY AGAINST DATA
    foreach($validation as $k => $v) {

        // DOES THE DATA ITEM EXIST?
        $valid = isset($data[$k]);

        // IF SO CHECK THE RULES
        if ($valid) {
            // CUSTOM VALIDATION HAPPENS HERE. WE MAKE A FUNCTION NAME OUT OF
            // THE type VALUE AND THEN CALL THE FUNCTION (IF IT EXISTS) WITH
            // WITH OUR FIELD DATA AND THE SUB-ARRAY FOR THIS ENTRY
            if (isset($v['type'])) {
                $function = "validate_{$v['type']}";
                if (function_exists($function)) {

                    // VALIDATION FUNCTIONS RETURN true / false
                    // WE USE RETURN TO TEST VALIDITY
                    $valid = $function($data[$k], $v);
                }
            }
           
            // IF NO TYPE IS DEFINED WE ASSUME EXISTENCE IS SUFFICIENT
        }
       
        // IF VALIDATION FAILED ADD THE ERROR MESSAGE (BY CONTROL ID) TO THE
        // ARRAY WE ARE GOING TO RETURN TO THE CALLING PROCESS
        if (!$valid) {
            // USE THE ERROR IN THE SUB-ARRAY (IF PRESENT) OTHERWISE USE DEFAULT
            $error[$k] = isset($v['msg']) ? $v['msg'] : 'Please enter a value';
        }
    }

    // RETURN ERRORS (IF ANY)
    return $error;
}


// CHECK FOR EXISTENCE ONLY AND OPTIONALLY LENGTH
function validate_exist($item, $v)
{
    // Get length if defined otherwise any length will do
    $length = isset($v['length']) ? $v['length'] : 0;
    return (strlen($item) >= $length);
}


// VALIDATE BY REGULAR EXPRESSION
function validate_regex($item, $v)
{
    // WAS A PATTERN DEFINED? IF SO USE IT, OTHERWISE MATCH ANYTHING
    $pattern = isset($v['pattern']) ? $v['pattern'] : '/.*/';

    return preg_match($pattern, $item);
}


// VALIDATE EMAIL - WE COULD HAVE USED A REGEX FOR THIS BUT WE
// WILL USE THE filter_var() FUNCTION TO DO IT HERE
function validate_email($item, $v)
{
    return filter_var($item, FILTER_VALIDATE_EMAIL) !== false;
} 

All that we need on the server is to add the code that collects the form data, sends it for validation and reports the result.

我们在服务器上所需要做的就是添加收集表单数据的代码,将其发送以进行验证并报告结果。

<?php
$response = new stdClass;

// ASSUME A NEGATIVE OUTCOME 
$response->status = false;
$response->message = "Invalid parameters";

// GET OUR FORM DATA SAFELY
$data = isset($_POST['data']) ? $_POST['data'] : false;

// CHECK DATA IS VALID
if ($data && is_array($data)) {
    // WE HAVE FORM INPUT SO ASSUME THE BEST AND 
    // SET A SUCCESS MESSAGE. THIS ONLY GETS USED IF THERE ARE NO ERRORS.
    $response->message = "Thank you for your input.";
   
    // THIS IS OUR VALIDATION ARRAY INDEXED BY FIELD
    $validate = array (
        'firstname' => array('msg' => 'Please enter a valid first name', 'type' => 'exist', 'length' => 3),
        'lastname' => array('msg' => 'Please enter a valid last name', 'type' => 'regex', 'pattern' => '/^[a-zA-Z\-]{3,}$/'),
        'email' => array('msg' => 'Please enter a valid email address', 'type' => 'email')
    );
   
    // GET ANY FIELD ERRORS THAT MAY EXIST
    $response->errors = validate($data, $validate);
   
    // STATUS IS SET BY WHETHER THERE WERE ANY ERRORS OR NOT
    $response->status = empty($response->errors);

    // IF NO ERRORS THEN WE CAN PROCESS THE FORM
    if ($response->status) {
      // DO VALID FORM PROCESSING HERE: SEND EMAIL, WRITE TO DB
    }
}


// RETURN OUR STATUS ARRAY
die(json_encode($response));


 

What we should get back in our AJAX call is a JSON object with errors and field id's so we can display custom errors or process valid form.

我们应该在AJAX调用中得到的是一个带有错误和字段ID的JSON对象,因此我们可以显示自定义错误或处理有效表单。

Here is how we handle the return in our jQuery code

这是我们处理jQuery代码中的返回值的方式

jQuery

jQuery的

<script>
$(function() {
    $('form').submit(function(e) {
        // PREVENT DEFAULT SUBMIT
        e.preventDefault();
       
        // JUST GOOD PRACTICE
        var frm = this;
       
        // SERIALIZE THE FORM DATA
        var data = $(frm).serialize();
       
        // GET THE DEFAULT FORM ACTION
        var action = $(frm).attr('action');
       
        // REMOVE ANY EXISTING .alert
        $('.alert').remove();
       
        // AJAX TO THE SERVER
        $.ajax({
            url: action,
            data: data,
            type: 'POST',
            dataType: 'JSON'
        }).done(function(resp) {
            // ALL IS WELL SO REPLACE THE FORM WITH THE
            // SUCCESS MESSAGE
            if (resp.status) {
                $(frm).html(resp.message);
            }
            else {
                // LOOP THROUGH ERRORS AND FOR EACH CREATE A <div>
                // WTIH THE MESSAGE AND ADD IT AFTER THE <input>
                for(var i in resp.errors) {
                    var error = $('<div/>', {class: 'alert alert-danger'}).html(resp.errors[i]);
                    $('#' + i).after(error);
                }
            }
        });
    });
});
</script> 

That's it - the basics of an AJAX form with customised validation and return error messages

就是这样-具有自定义验证和返回错误消息的AJAX表单的基础

Here is a screen shot of a failed validation attempt

这是验证尝试失败的屏幕截图

The above shows that there was a problem with the firstname and the email address. Let's look at the console (F12) to see what was returned.

上面显示,名字和电子邮件地址有问题。 让我们看一下控制台(F12),看看返回了什么。

From the above we can see that the return status was "false". You will notice there is a success message in the return. This is because the return object by default is a success and we override it when a validation fails. 

从上面我们可以看到返回状态为“ false”。 您会发现返回中有一条成功消息。 这是因为默认情况下,返回对象是成功的,并且验证失败时我们将覆盖它。

The error array shows the fields that failed and the message to show for each field.

错误数组显示失败的字段以及每个字段要显示的消息。

A full listing for reproducing the above is shown below

复制上面的内容的完整列表如下所示

HTML

HTML

<!doctype html>
<html>
<title>AJAX, jQuery form submission with server side field validation</title>
<head>
</head>
<body>
<form class="form" action="validate.php">
    <div class="row">
        <label for="firstname" class="col-md-3">First Name</label>
        <div class="col-md-9">
            <input type="text" name="data[firstname]" id="firstname" class="form-control" />
        </div>
        <label for="lastname" class="col-md-3">Last Name</label>
        <div class="col-md-9">
            <input type="text" name="data[lastname]" id="lastname" class="form-control" />
        </div>
        <label for="email" class="col-md-3">Email</label>
        <div class="col-md-9">
            <input type="text" name="data[email]" id="email" class="form-control" />
        </div>
        <button class="pull-right btn btn-primary">Send</button>
    </div>
</form>
<script src="http://code.jquery.com/jquery.js"></script>
<script>
$(function() {
    $('form').submit(function(e) {
        // PREVENT DEFAULT SUBMIT
        e.preventDefault();
       
        var data = $(this).serialize();
        var frm = this;
        var action = $(frm).attr('action');
        $('.alert').remove();
        $.ajax({
            url: action,
            data: data,
            type: 'POST',
            dataType: 'JSON'
        }).done(function(resp) {
            if (resp.status) {
                $(frm).html(resp.message);
            }
            else {
                for(var i in resp.errors) {
                    var error = $('<div/>', {class: 'alert alert-danger'}).html(resp.errors[i]);
                    $('#' + i).after(error);
                }
            }
        });
    });
});
</script> 

PHP Listing  {validate.php}

PHP清单 { validate.php}

<?php
$response = new stdClass;
$response->status = false;
$response->message = "Invalid parameters";
$data = isset($_POST['data']) ? $_POST['data'] : false;
if ($data &amp;&amp; is_array($data)) {
    // we have valid form input
    $response->message = "Thank you for your input.";
    $validate = array (
        'firstname' => array('msg' => 'Please enter a valid first name', 'type' => 'exist', 'length' => 3),
        'lastname' => array('msg' => 'Please enter a valid last name', 'type' => 'regex', 'pattern' => '/^[a-zA-Z\-]{3,}$/'),
        'email' => array('msg' => 'Please enter a valid email address', 'type' => 'email')
    );
   
    $response->errors = validate($data, $validate);
    $response->status = empty($response->errors);
}
die(json_encode($response));


function validate($data, $validation)
{
    // we only need to check the validation array and
    // then use thekeys to see if the values exist in the data array
    $error = array();
    foreach($validation as $k => $v) {
        $valid = isset($data[$k]);
        if ($valid) {
            if (isset($v['type'])) {
                $function = "validate_{$v['type']}";
                if (function_exists($function)) {
                    $valid = $function($data[$k], $v);
                }
            }
        }
        if (!$valid) {
            $error[$k] = isset($v['msg']) ? $v['msg'] : 'Please enter a value';
        }
    }
   
    return $error;
}


function validate_exist($item, $v)
{
    $length = isset($v['length']) ? $v['length'] : 0;
    return strlen($item) >= $length;
}


function validate_regex($item, $v)
{
    $pattern = isset($v['pattern']) ? $v['pattern'] : '/.*/';
    return preg_match($pattern, $item);
}


function validate_email($item, $v)
{
    return filter_var($item, FILTER_VALIDATE_EMAIL) !== false;
} 

翻译自: https://www.experts-exchange.com/articles/29534/AJAX-form-submission-with-customized-server-field-validation.html

web 表单自定义字段

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值