HTML5表单验证机制:在服务器端验证后设置invalidate

时间:2014-02-05 10:04:42

标签: php html5 forms css3 validation

好吧,标题是如此奇怪,我当然应该告诉你发生了什么:)。我正在创建一个HTML5表单。我希望使用HTML5新技术和CSS3新伪类(当然我记得有关服务器端验证)来完全验证该表单。我举一个例子:

HTML:

<input type="email" value=""> 

CSS:

input:invalid {color: #fff; box-shadow: 0 0 5px #f00;}

众所周知:良好的验证是在用户浏览器和服务器上严格相同的。因此,如果我允许用​​户只输入电子邮件号码,服务器将接受信件是一个错误。如果用户可以输入数字而服务器不接受,那就错了。

有什么问题?我要求用户发送电子邮件。用户输入asd @ asd这是HTML5命名法中完美验证的电子邮件(asd可以是localhost,因此不需要点)。这就是输入验证的原因,一切正常。现在,我将这封电子邮件发送到我的PHP脚本,这是非常苛刻的要求。例如,它:

PHP

function Validate($mail) {
    $validate = true;

    // Parse mail
    if (!filter_var($mail, FILTER_VALIDATE_EMAIL)) $validate = false;

    // Check DNS RR
    $host = explode('@',$mail);
    $host = array_pop($host);
    if ($host == '') $validate = false;
    else if (!checkdnsrr($host,'MX')) $validate = false;

    return $validate;
}

因此,电子邮件asd @ asd当然不会通过此验证。

是否有任何机制可以让我向浏览器建议此电子邮件仍然不好,但使用HTML5方法?

更确切地说。我在第一次检查POST数据时写了一个PHP表单类wchich,然后渲染表单。因此,如果缺少某些内容,我可以渲染表单,但使用发送的POST数据,不要忘记输入值。这是做这种事情的常用方法。

所以我在PHP知道电子邮件无效后呈现输入电子邮件,但HTML5认为它是有效的。更多代码(真正的片段向您展示这个想法......):

$email = isset($_POST['email']) ? $_POST['email'] : '';
if (Validate($email)) {
    // do whatever You want with the form
    header("Location: /success-congratulations-great-form-hoooray");
}
else {
    echo "<form>...";
    echo "<input type="email" value=\"$email\">"; // this $email is important here!
    echo "<input type=\"submit\" ... />
    echo "</form>";
}

是否有机会建议浏览器此输入无效?只有在验证错误的情况下,才考虑回复某种<script>。但我被困在这里。

我认为这个问题,例子和答案对许多人来说都很有用,他们希望制作一个符合标准的表格,却错过了一些东西......

感谢您的回复和最好的问候!

更新 真的没有想法我怎么能实现这个目标?我正在考虑开始赏金:)。

2 个答案:

答案 0 :(得分:2)

好的,我已经回答了我自己的问题。多么自私的事情。如果PHP返回invalidate,那么我们可以回显

echo '<input name="mail" .... data-validate="This email address does not exist" />';

然后在包含javascript后,检查输入是否有自己的data-validate属性。如果是,请设置自定义有效性消息(在文档就绪时),例如:

$(document).ready(function() {
    var elements = $('input[data-validate]');
    for (var i = 0; i < elements.length; i++) { 
        var error = $(elements[i]).attr('data-validate');
        elements[i].setCustomValidity(error);
        $(elements[i]).removeAttr('data-validate');
    }
});

在这种情况下,我们可以使用html5验证机制AFTER php验证返回错误。并且php具有的相同错误将返回给用户。 什么是伟大的语义解决方案!!!! 如果输入不正确,您可以输入几条不同的消息。例如&#34;域名不存在&#34;,&#34; Mail没有@在其中!&#34;等...

希望它有所帮助......你对这个解决方案有什么看法? 我会等待评论,如果有人给我+1,我会把它标记为已回答......因为我回答自己感觉很奇怪。

<强>更新 正如我想的那样,事情并非如此简单。这不是一个100%的好答案,但是,这是一个好主意:)。问题是,在设置自定义有效性后,表单无法再提交。所以Javascript也应该触发提交点击功能,然后将所有自定义有效性重置为初始状态。

真实答案

所以......这样做不是一个好主意。让标准赶上现实,让我们等到时代,浏览器真正检查电子邮件的存在性。到这个时候,在浏览器端做任何事情都可以验证,并将主要的强验证留给服务器端。如果出现问题,请使用您自己的错误报告机制,并且不要尝试使用jquery将它们反映回php到html5。因为这太复杂了,不值得你的时间:)。如果有人有其他想法,或知道如何做到这一点,请写下另一个答案。我会读它,并将其标记为已解决。在那段时间之前,我认为我的做法是另一种方式&#34;经过几天的研究,答案已经足够好了。

简而言之:让html5验证你的表单和html5一样好,如果强大的服务器端验证拒绝这个表单,那就做一个好的信息出错了,以及用户应该改进什么来验证。

谢谢大家的回答,最好的问候。

答案 1 :(得分:0)

前一段时间,当我尝试使用正则表达式验证电子邮件时,我遇到了与电子邮件验证相同的问题。我搜索了网络,发现了这个功能......

function validateMail($email) {
    $isValid = true;
    $atIndex = strrpos($email, "@");
    if (is_bool($atIndex) && !$atIndex) {
        return false;
    }
    else {
        $domain = substr($email, $atIndex+1);
        $local = substr($email, 0, $atIndex);
        $localLen = strlen($local);
        $domainLen = strlen($domain);
        if ($localLen < 1 || $localLen > 64) {
            return false;
        }
        else if ($domainLen < 1 || $domainLen > 255) {
            return false;
        }
        else if ($local[0] == '.' || $local[$localLen-1] == '.') {
            return false;
        }
        else if (preg_match('/\\.\\./', $local)) {
            return false;
        }
        else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
            return false;
        }
        else if (preg_match('/\\.\\./', $domain)) {
            return false;
        }
        else if(!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/',
                       str_replace("\\\\","",$local))) {
            if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local))) {
                return false;
            }
        }
        if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))) {
            return false;
        }
    }

    return $isValid;
}

在文章中它说该功能基于RFC-5322标准。它永远不会让我失望。