2

名前、有効な電子メール、コメントの 3 つのフィールドをチェックする電子メール フォームがあります。しかし、現在の設定方法では、名前とコメントが1つの関数に含まれているため、電子メールが有効でない場合でも最初に名前とコメントをチェックします。フィールドを順番にチェックするように書き直すにはどうすればよいですか。また、ユーザーが再度入力する必要がないように、エラーのないフィールドを再表示したいと考えています。助けてください。ありがとう

<?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();
}
?>
4

4 に答える 4

5

まず、すべてのフィールドを一度に検証し、適切なエラー メッセージをすべてフォームに表示することをお勧めします。主な理由は、一度に 1 つのエラーに対処しなければならないため、何度もフォームを送信しなければならない場合、ユーザー エクスペリエンスが低下する可能性があることです。次のエラーが何であるかを明らかにするために一度に 1 つずつ修正するのではなく、メール アドレス、パスワード、コメント、および選択内容を一度に修正したいと思います。

そうは言っても、フォームを必要に応じて検証するためのヒントがいくつかあります。これは通常、ユーザーがやりたいことを実行するフォームにアプローチする方法です。これは、フォーム HTML とフォーム プロセッサ (PHP) が同じファイルにまとめられていることを前提としています (これが現在のファイルです)。2 つに分けることはできますが、その方法は少し異なる場合があります。

  • フォームを出力し、エラー メッセージを認識し、以前のフォーム入力 (存在する場合) にアクセスできる関数またはコード ブロックを 1 つ用意します。通常、これは関数の外に残すことができ、PHP スクリプトのコードの最後のブロックにすることができます。
  • エラー メッセージの配列を設定します (例: $errors = array())。この配列が空の場合、送信にエラーがなかったことがわかります
  • フォームが出力される前に、スクリプトの上部付近でフォームが送信されたかどうかを確認してください。
  • フォームが送信された場合は、各フィールドを 1 つずつ検証し、フィールドにエラーが含まれている場合は、エラー メッセージを$errors配列に追加します (例: $errors['password'] = 'Passwords must be at least 8 characters long';)
  • フォーム入力に以前の値を再入力するには、入力した値をどこかに保存する必要があります (単に配列を使用するか、サニタイズして値を個々の変数または配列に$_POST割り当てることができます。$_POST
  • すべての処理が完了したら、エラーをチェックして、この時点でフォームを処理できるかどうか、またはユーザーからの新しい入力が必要かどうかを判断できます。
  • これを行うには、通常、次のようなことを行いますif (sizeof($errors) > 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>

ここで見ることができるより高度な例があり、同様にいくつかのガイダンスを提供する可能性があります。

それが役立つことを願っています。

于 2012-04-18T23:32:26.960 に答える
1

filter_varおよびin_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
}?>
于 2012-04-18T23:58:07.190 に答える
1

最も簡単なオプションは、フォーム検証ライブラリを使用することです。たとえば、PHP のフィルター拡張機能は、完全なソリューションではありませんが、一部の型の検証とサニタイズを提供します。

自分で実装することを主張する場合、考慮しなければならない問題の 1 つは、順序としてカウントされるものです。フォーム内の要素の順序またはユーザー入力の順序です$_POST。ほとんどのブラウザーでは、これらは同じはずですが、これを強制する標準はありません。フォームの順序を変更したい場合は、フォーム構造を 1 か所で定義し、その情報を使用してフォームの生成や検証などを行う必要があります ( Don't Repeat Yourself (DRY) 原則の結果です)。 )。適切な構造を反復すると、希望する順序が得られます。フォームをループするとフォームの順序が得られますが、ループ$_POSTを使用するとユーザー入力の順序が得られます。

単にデータを検証する以上のことを望んでいるようです。また、「サニタイズ」と呼ばれるプロセスを使用する準備も必要です。

サニタイズに関しては、単一の関数ではなく、さまざまな種類のサニタイザーを定義しcheck_inputます。特定のサニタイザーは、関数、またはメソッドを持つオブジェクトである可能性があります__invoke。フォーム フィールドからサニタイザーへのマップを作成します (たとえば、サニタイザー コールバックへの入力名の配列)。マッピング内の要素の順序によって、サニタイズの順序が設定されます。単一の構造体を使用してフォーム情報を定義する場合、表示順序とサニタイズ順序は同じになります。

非常に大まかな概要は次のとおりです。

# $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 属性の場合、これは (eg) を使用することを意味しますhtmlspecialchars。送信データのみをエスケープする必要があることに注意してください。これは、サニタイズ関数が を呼び出すべきではないことを意味しますhtmlspecialchars

各エラーを対応する入力の横に配置し、「エラー」クラスを要素に追加し、「エラー」クラスをスタイルして目立つようにすることで、使いやすさを向上させることができます。<label>ラベル テキストを要素で囲むことにより、アクセシビリティを向上させます。

于 2012-04-18T23:27:23.207 に答える
1

次のスクリプト構造を使用します。

<?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>
于 2012-04-18T23:18:22.513 に答える