ユーザーがEnter
を2回押すと、投稿が2回挿入されることがあります。
同じtitle
とcontent
の投稿が既に存在するかどうかを確認する以外に、これを防ぐ解決策はありますか?
この問題にはいくつかの解決策があります。
JavaScriptを使用して、フォームが送信されたときにフォームの送信ボタンを無効にします。これの欠点は、これが絶対に確実な方法ではないことです。ボタンを実際にクリックせずにフォームを送信するのは非常に簡単です。これは、JavaScriptが無効になっているユーザーにとっても機能しません。 この方法は絶対にお勧めしません。
例:
<script language="javascript">
<!--
function disableSubmitButton() {
// you may fill in the blanks :)
}
-->
</script>
<form action="foo.php" method="post">
<input type="text" name="bar" />
<input type="submit" value="Save" onclick="disableSubmitButton();">
</form>
PHPセッション を使用して、セッション変数(たとえば、$ _ SESSION ['posttimer'])をポストの現在のタイムスタンプに設定します。PHPでフォームを実際に処理する前に、$ _ SESSION ['posttimer']変数が存在するかどうかを確認し、特定のタイムスタンプの違い(IE:2秒)を確認します。このようにして、二重送信を簡単に除外できます。
例:
// form.html
<form action="foo.php" method="post">
<input type="text" name="bar" />
<input type="submit" value="Save">
</form>
// foo.php
if (isset($_POST) && !empty($_POST))
{
if (isset($_SESSION['posttimer']))
{
if ( (time() - $_SESSION['posttimer']) <= 2)
{
// less then 2 seconds since last post
}
else
{
// more than 2 seconds since last post
}
}
$_SESSION['posttimer'] = time();
}
各POSTに一意のトークンを含めます。この場合、セッション変数を含めるトークンに設定し、そのトークンをフォーム。フォームが送信されたら、トークンを再生成します。送信されたトークンがセッション内のトークンと一致しない場合、フォームは再送信されているため、無効と宣言する必要があります。
例:
// form.php
<?php
// obviously this can be anything you want, as long as it is unique
$_SESSION['token'] = md5(session_id() . time());
?>
<form action="foo.php" method="post">
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" />
<input type="text" name="bar" />
<input type="submit" value="Save" />
</form>
// foo.php
if (isset($_SESSION['token']))
{
if (isset($_POST['token']))
{
if ($_POST['token'] != $_SESSION['token'])
{
// double submit
}
}
}
ポストで一意のトークンを使用して、各ポスト/ポストバックが一度だけ処理されるようにします。
人々がJavaScriptをオフにしたり、他の奇妙なことをしたりする可能性があるため、送信ボタンを無効にすることはあまり良い解決策ではありません。クライアント側の検証は適切な出発点ですが、常にサーバー側の処理でもバックアップする必要があります。
フォームとともに送信する一意の1回限りの使用キーを生成します。
ユーザーがクライアントでJavascriptを無効にしている可能性があるため、JavaScriptに依存することはお勧めできません。キースキームを使用すると、送信がサーバーによって受信されたときに、そのキーの送信をロックできます。重複した送信には、好きなように応答できます。
このアプローチが機能するには、キーが一意であり、予測が非常に困難である必要があります。そうしないと、キーの衝突により一部のフォームがロックされる可能性があります。したがって、すべてのフォーム送信のキーを追跡して衝突を回避する必要はありません。キーはそのユーザーのセッションで期限切れになるはずです。もう1つの注意点は、悪意のあるユーザーがキーを予測できる場合、コードが何らかのハイジャックまたはDOSエクスプロイトに対して脆弱になる可能性があることです。
重複フォーム送信の防止 は、JavaScriptなしでそれを行う方法を示しています。
私はこれを使います:
$form_token = $_SESSION['form_token'] = md5(uniqid());
$ form_tokenをフォームと一緒に送信します...
Form_tokenを確認します。
if($_SESSION['form_token'] != $_POST['form_token']) {
echo 'Error';
}
フォームが送信されたら、JavaScriptを使用して送信ボタンを無効にします(onsubmit
)。
ユーザーがJavaScriptを無効にしている場合でも、2回送信できることに注意してください。これが頻繁に発生してコードをチェックインすることを正当化できるかどうか(質問で提案したとおり)は、あなた次第です。
または、1回限りのフォームキーを使用します。
ユーザーが最終的に送信ボタンを押すことができる確認ページを作成する別の方法。この種の可能性を減らすかもしれません。
私はaction.phpで次のことをしています
if($_SESSION && isset($_SESSION['already_submitted'])) {
# If already submitted just redirect to thank you page
} else {
# If first submit then assign session value and process the form
$_SESSION['already_submitted'] = true;
# Process form
}
注:常にセッション内でsession_start()を使用してセッションを開始してください。
ユーザーがJavaScriptを使用してフォームを送信したら、送信ボタンを無効にします。これは、たとえば、質問に答えるときにStackOverflowが使用するものです。
例えば
<input type="submit" onclick="this.disabled=true" />
JavaScriptを使用して、ボタンをクリックするとすぐにボタンを無効にします。
onclick="this.disabled=true;forms[0].submit();"
送信を2回押すと、めったに複数の挿入が行われませんが、完全に単純なソリューションが必要な場合は、
onsubmit="document.getElementById('submit').disabled = true"
送信ボタンid="submit"