Многие начинающие веб-мастера задаются вопросом: "Как предотвратить повторную отправку данных из формы?". Очень часто вижу такие вопросы на форумах. В этой статье расскажу об легком и правильном способе решения этой проблемы.
Допустим, мы делаем скрипт, который принимает данные из формы, переданные методом POST. Скрипт данные принял, обработал и выдал страницу с результатом. Но если пользователь вздумает обновить страницу в этот момент — он увидит сообщение такого плана:
Чтобы отобразить эту страницу, Firefox должен отправить информацию, которая повторит любое ранее произведённое действие (например, запрос на поиск или онлайн-покупка).
И две кнопки. Нажатие на одну из них отправит данные повторно, что часто нежелательно. Нажатие на вторую не произведет обновления страницы. В любом случае, пользователю не хорошо от такого сообщения. Пользователи вообще не очень любят всякие внезапно выскакивающие окошки.
Для начала, покажу скрипт, который мы будем дорабатывать.
<html>
<head>
<?php
$data = $_POST['data'];
?>
</head>
<body>
<form action="index.php" method="post">
<input value="Данные" type="text" name="data" >
<input type="submit" value="Ok">
</form>
</body>
</html>
Можете отправить форму один раз, а потом нажать Ctrl+R и увидеть злополучное окно. Давайте от него избавляться.
Но сперва слово спонсору поста — сайту с полезным контентом для телефонов Samsung, который предлагает темы для samsung gt s5230, обои и прочий стафф.
Чтобы предотвратить повторную отправку данных формы можно делать серверный редирект. Это делается путем посылки браузеру заголовка Location с нужным урл. Например, это должна быть страница с благодарностью за заполненную форму. Тогда мы напишем что-то в духе:
<html>
<head>
<?php
$data = $_POST['data'];
if($data) {
header('Location: thank-you.html');
exit();
}
?>
</head>
<body>
<form action="index.php" method="post">
<input value="Данные" type="text" name="data" >
<input type="submit" value="Ok">
</form>
</body>
</html>
В этом случае сервер получит данные, обработает их и вместо показа результата отправит клиента на страницу, где этот результат будет показан.
Недостаток этого метода состоит в том, что пользователь может нажать кнопку "Назад" и вернуться на страницу с редиректом. Она снова швырнет его вперед и так пользователь с трудом сможет вернуться на две страницы назад, к форме, которую изначально заоплнял.
Клиентский редирект называется клиентским потому что он происходит на стороне клиента. То есть в браузере. Клиентский редирект может происходить при помощи JavaScript и meta-тегов.
У JavaScript есть преимущество — он перезаписывает History браузера так, что даже если пользователь нажмет кнопку "Назад" браузера, он не вернется на страницу, которую отдал обработчик формы. То есть, окошко исчезнет капитально. Но JS у некоторых отключен.
У META-тегов, с другой стороны, есть преимущество в плане универсальности. Они редиректят всех и всегда.
Оптимально будет сочетать эти два способа. Как — описал Александр Шуркаев в заметке оптимальный редирект.
Используем его метод следующим образом.
<html>
<head>
<?php
$data = $_POST['data'];
if($data) {
?>
<script type="text/javascript">
<!--
location.replace("index.php");
//-->
</script>
<noscript>
<meta http-equiv="refresh" content="0; url=index.php">
</noscript>
<?php
}
?>
</head>
<body>
<form action="index.php" method="post">
<input value="Данные" type="text" name="data" >
<input type="submit" value="Ok">
</form>
</body>
</html>
Пробуем! Теперь, как видно, никакого окна не появляется. Что мы сделали? Мы проверили. Если данные пришли — мы выводим все необходимое для редиректа. В принципе, после этого уже можно даже делать exit, чтобы не грузить браузер лишними данными, которые все равно никто не увидит.