【问题标题】:PHP Show error messages in order and re-display correct fieldsPHP 按顺序显示错误消息并重新显示正确的字段
【发布时间】:2012-04-18 22:55:47
【问题描述】:

我有一个电子邮件表单,它检查三个字段,名称、有效电子邮件和 cmets。但是它现在的设置方式,由于 name 和 cmets 在一个函数中,即使电子邮件无效,它也会首先检查 name 和 cmets,我如何重新编写它以便按顺序检查字段。另外,我想重新显示没有错误的字段,这样用户就不必再次输入。请帮忙。谢谢

<?php
$myemail = "comments@myemail.com";
$yourname = check_input($_POST['yourname'], "Enter your name!");
$email = check_input($_POST['email']);
$phone = check_input($_POST['phone']);
$subject = check_input($_POST['subject']);
$comments = check_input($_POST['comments'], "Write your comments!");

if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/", $email))
  {
    show_error("Enter a valid E-mail address!");
  }

exit();

function check_input($data, $problem='')
 {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
if ($problem && strlen($data) == 0)
{
    show_error($problem);
}
return $data;
}

function show_error($myError)
{
?>
<!doctype html>
<html>
<body>
<form action="myform.php" method="post">
 <p style="color: red;"><b>Please correct the following error:</b><br />
 <?php echo $myError; ?></p>
 <p>Name: <input type="text" name="yourname" /></P>
 <P>Email: <input type="text" name="email" /></p>
 <P>Phone: <input type="text" name="phone" /></p><br />
 <P>Subject: <input type="text" style="width:75%;" name="subject" /></p>
 <p>Comments:<br />
 <textarea name="comments" rows="10" cols="50" style="width: 100%;"></textarea></p>
 <p><input type="submit" value="Submit"></p>
</form>
</body>
</html>
<?php
exit();
}
?>

【问题讨论】:

  • 我试图将正则表达式放入 check_input 函数中,但无论如何都会显示电子邮件错误。

标签: php forms


【解决方案1】:

首先,我建议您一次验证所有字段,并在表单上显示所有适当的错误消息。主要原因是如果他们必须一次提交你的表单很多次,这可能会导致糟糕的用户体验,因为他们必须一次解决一个错误。我宁愿一次更正我的电子邮件地址、密码、cmets 和选择,而不是一次修复一个,只是为了揭示下一个错误是什么。

也就是说,这里有一些关于验证表单的提示。这通常是我处理表单做你想做的事情的方式。这假设您的表单 HTML 和表单处理器 (PHP) 在同一个文件中(这就是您现在所拥有的)。您可以将两者分开,但这样做的方法可能会有所不同。

  • 拥有一个输出表单的函数或代码块,并且知道您的错误消息,并且可以访问之前的表单输入(如果有)。通常,这可以放在函数之外,并且可以是 PHP 脚本中的最后一段代码。
  • 为错误消息设置一个数组(例如$errors = array())。当此数组为空时,您知道提交没有错误
  • 在表单输出之前检查表单是否已提交到靠近脚本顶部的位置。
  • 如果表单已提交,则一次验证每个字段,如果某个字段包含错误,则将错误消息添加到 $errors 数组(例如 $errors['password'] = 'Passwords must be at least 8 characters long';
  • 要使用以前的值重新填充表单输入,您必须将输入的值存储在某处(您可以只使用$_POST 数组,或者清理并将$_POST 值分配给单个变量或数组.
  • 所有处理完成后,您可以检查是否有任何错误,以决定此时是否可以处理表单,还是需要用户提供新的输入。
  • 为此,我通常会执行if (sizeof($errors) &gt; 0) { // show messages } else { // process form } 之类的操作
  • 如果您要重新显示表单,您只需为每个表单元素添加一个value="" 属性并回显用户提交的值。 使用 htmlspecialchars() 或类似函数对输出进行转义非常重要

有了这些东西,这里是你的表单的一些返工来做到这一点:

<?php
$myemail = "comments@myemail.com";
$errors  = array();
$values  = array();
$errmsg  = '';

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    foreach($_POST as $key => $value) {
        $values[$key] = trim(stripslashes($value)); // basic input filter
    }

    if (check_input($values['yourname']) == false) { 
        $errors['yourname'] = 'Enter your name!';
    }

    if (check_input($values['email']) == false) {
        $errors['email'] = 'Please enter your email address.';
    } else if (!preg_match('/([\w\-]+\@[\w\-]+\.[\w\-]+)/', $values['email'])) {
        $errors['email'] = 'Invalid email address format.';
    }

    if (check_input($values['comments']) == false) {
        $errors['comments'] = 'Write your comments!';
    }

    if (sizeof($errors) == 0) {
        // you can process your for here and redirect or show a success message
        $values = array(); // empty values array
        echo "Form was OK!  Good to process...<br />";
    } else {
        // one or more errors
        foreach($errors as $error) {
            $errmsg .= $error . '<br />';
        }
    }
}

function check_input($input) {
    if (strlen($input) == 0) {
        return false;
    } else {
        // TODO: other checks?

        return true;
    }
}
?>
<!doctype html>
<html>
<body>
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post">
 <?php if ($errmsg != ''): ?>
 <p style="color: red;"><b>Please correct the following errors:</b><br />
 <?php echo $errmsg; ?>
 </p>
 <?php endif; ?>

 <p>Name: <input type="text" name="yourname" value="<?php echo htmlspecialchars(@$values['yourname']) ?>" /></P>
 <P>Email: <input type="text" name="email" value="<?php echo htmlspecialchars(@$values['email']) ?>" /></p>
 <P>Phone: <input type="text" name="phone" value="<?php echo htmlspecialchars(@$values['phone']) ?>"/></p><br />
 <P>Subject: <input type="text" style="width:75%;" name="subject" value="<?php echo htmlspecialchars(@$values['subject']) ?>" /></p>
 <p>Comments:<br />
 <textarea name="comments" rows="10" cols="50" style="width: 100%;"><?php echo htmlspecialchars(@$values['comments']) ?></textarea></p>
 <p><input type="submit" value="Submit"></p>
</form>
</body>
</html>

我有一个更高级的示例,您可以查看here,它也可以为您提供一些指导。

希望对您有所帮助。

【讨论】:

  • 漂亮的头像 ;)。幸运的是,我们过去常常在 stackoverflow 上频繁使用不同的房间。
  • @terencehill thumbsup :)
【解决方案2】:

最简单的选择是使用form validation library。例如,PHP 的 filter 扩展为某些类型提供验证和清理,尽管它不是一个完整的解决方案。

如果您坚持自己实现它,您必须考虑的一个问题是什么才是顺序:表单中元素的顺序或$_POST 中用户输入的顺序。在大多数浏览器上,这些应该是相同的,但没有强制执行此的标准。如果您想脱离表单顺序,您需要在一个地方定义表单结构,并使用该信息来执行诸如生成或验证表单之类的事情(Don't Repeat Yourself (DRY) 原则的结果)。遍历适当的结构会给你想要的顺序:循环表单会给你表单顺序,而循环 $_POST 会给你用户输入的顺序。

看起来您想要的不仅仅是验证数据;您还需要准备使用它,这个过程称为“消毒”。

在消毒方面,定义不同种类的消毒剂,而不是单一的check_input 函数。特定的消毒剂可以是函数,也可以是具有__invoke 方法的对象。创建表单字段到 sanitizer 的映射(例如,输入名称数组到 sanitizer 回调)。映射中元素的顺序决定了清理的顺序;如果使用单一结构来定义表单信息,则显示顺序和清理顺序将因此相同。

这是一个非常广泛的大纲:

# $fields could be form structure or user input
foreach ($fields as $name => $data) {
    # sanitize dispatches to the appropriate sanitizer for the given field name
    $form->sanitize($name, $data);
    # or:
    //sanitize($name, $data);
    # or however you choose to structure your sanitization dispatch mechanism
}

至于将输入的值设置为用户提供的数据,只需在输出元素时输出元素值即可。与所有用户输入(实际上,所有格式化输出)一样,在输出数据时正确转义数据。对于 HTML 属性,这意味着使用(例如)htmlspecialchars。请注意,您应该只转义传出数据。这意味着您的清理函数不应调用htmlspecialchars

您可以通过将每个错误放在相应的输入旁边、向元素添加“错误”类并设置“错误”类的样式以使其突出来提高可用性。通过在标签文本周围包裹&lt;label&gt; 元素来提高可访问性。

【讨论】:

  • 我是 PHP 新手,非常感谢您的信息。谢谢!
【解决方案3】:

使用这种脚本结构:

<?php
$errors = array();

if (isset($_POST['send'])) {
    // check data validity
    if (!mailValid($_POST['email']))
        $errors[] = 'Mail is not valid';
    ...

    // send data by email
    if (!$errors) {
        // send mail and redirect
    }
}
?>
<html>
    ...
    <?php
    if ($errors) {
        // display errors
        foreach ($errors as $error) {
            echo "$error<br />";
        }
    }
    ?>
    <form ...>
        ...
        Email: <input type="text" name="email" value="<?php echo isset($_POST['email']) ? htmlspecialchars($_POST['email']) : '' ?>" />
        ...
    </form>
    ...
</html>

【讨论】:

    【解决方案4】:

    您总是可以这样做,使用 filter_varin_array 检查:

    <?php
    $myemail = "comments@myemail.com";
    
    //Pre made errors array
    $errors=array('name'=>'Enter Your name',
                  'email'=>'Please enter valid email',
                  'phone'=>'Please enter valid phone number',
                  'subject'=>'Please enter valid subject, more then 10 chars',
                  'comment'=>'Please enter valid comment, more then 10 chars');
    
    //Allowed post params and its validation type
    $types = array('name'=>'string',
                   'email'=>'email',
                   'phone'=>'phone',
                   'subject'=>'string',
                   'comment'=>'string');
    
    //A simple validation function using filter_var
    function validate($value,$type){
        switch ($type){
            case "email":
                return ((filter_var($value, FILTER_VALIDATE_EMAIL))?true:false);
                break;
            case "phone":
                return ((preg_match("/^[0-9]{3}-[0-9]{4}-[0-9]{4}$/", $value))?true:false);
                break;
            case "string":
                return ((strlen($value) >=10 )?true:false);
                break;
    
            default:
                return false;
                break;
        }
    }
    
    
    //If forms been posted
    if(!empty($_POST) && $_SERVER['REQUEST_METHOD'] == 'POST'){
        //Assign true, if all is good then this will still be true
        $cont=true;
        $error=array();
        foreach($_POST as $key=>$value){
          //if key is in $types array
          if(in_array($key,$types)){
            //If validation true
            if(validate($value, $types[$key])==true){
                $$key=filter_var($value, FILTER_SANITIZE_STRING);
            }else{
                //Validation failed assign error and swithc cont to false
                $error[$key]=$errors[$key];
                $cont=false;
            }
          }
        }
    }
    
    if($cont==true && empty($error)){
        //Send mail / do insert ect
    }else{
        //Default to form
    ?>
    <!doctype html>
    <html>
    <body>
    <form action="" method="post">
     <p>Name: <input type="text" name="name" value="<?=@htmlentities($name);?>"/> <?=@$error['name'];?></P>
     <P>Email: <input type="text" name="email" value="<?=@htmlentities($email);?>" /> <?=@$error['email'];?></p>
     <P>Phone: <input type="text" name="phone" value="<?=@htmlentities($phone);?>"/> <?=@$error['phone'];?></p><br />
     <P>Subject: <input type="text" style="width:75%;" name="subject" /> <?=@$error['subject'];?></p>
     <p>Comments: <?=@$error['comment'];?><br />
     <textarea name="comment" rows="10" cols="50" style="width: 100%;"><?=@htmlentities($comment);?></textarea></p>
     <p><input type="submit" value="Submit"></p>
    </form>
    </body>
    </html>
    <?php
    }?>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-25
      • 1970-01-01
      • 1970-01-01
      • 2015-07-03
      • 1970-01-01
      • 1970-01-01
      • 2013-11-15
      • 2013-07-16
      相关资源
      最近更新 更多