Как предотвратить повторную отправку формы при обновлении страницы
Привет! У меня есть форма, которая добавляет вложения к записи, однако когда форма отправляется, она просто выводит "ваш файл был загружен", не показывая запись с новым вложением. Когда пользователь обновляет страницу (чтобы увидеть новое вложение), форма отправляется снова!
Возможно ли либо (1) предотвратить повторную отправку формы при обновлении, (2) автоматически обновить страницу для отображения записи с новым вложением?? (вариант 2 гораздо лучше)
<?php $post_id = $post->ID;
if ( isset( $_POST['html-upload'] ) && !empty( $_FILES ) ) {
require_once(ABSPATH . 'wp-admin/includes/admin.php');
$id = media_handle_upload('async-upload', $post_id); //id записи страницы файлов клиента
unset($_FILES);
if ( is_wp_error($id) ) {
$errors['upload_error'] = $id;
$id = false;
}
if ($errors) {
echo "<p>При загрузке файла произошла ошибка.</p>";
} else {
echo "<p>Ваш файл был загружен.</p>";
}
}
?>
<form id="file-form" enctype="multipart/form-data" action="<?php echo $_SERVER['REQUEST_URI']; ?>" method="POST">
<p id="async-upload-wrap"><label for="async-upload">загрузить</label>
<input type="file" id="async-upload" name="async-upload"> <input type="submit" value="Загрузить" name="html-upload"></p>
<p><input type="hidden" name="post_id" id="post_id" value="<?php echo $post_id ?>" />
<?php wp_nonce_field('client-file-upload'); ?>
<input type="hidden" name="redirect_to" value="<?php echo $_SERVER['REQUEST_URI']; ?>" /></p>
<p><input type="submit" value="Сохранить все изменения" name="save" style="display: none;"></p>
</form>
Спасибо! :)
Вместо …
} else {
echo "<p>Ваш файл был успешно загружен.</p>";
}
… перенаправьте на другой адрес при успешной загрузке:
} else {
$new_url = add_query_arg( 'success', 1, get_permalink() );
wp_redirect( $new_url, 303 );
exit;
}
Код состояния 303 инициирует GET-запрос:
Этот метод существует в первую очередь для того, чтобы вывод скрипта, активированного через POST, мог перенаправить пользовательский агент к выбранному ресурсу. Новый URI не является заменой первоначально запрошенного ресурса. Ответ 303 НЕ ДОЛЖЕН кэшироваться, но ответ на второй (перенаправленный) запрос может быть кэшируемым.
В обработчике формы сначала проверьте, установлен ли параметр $_GET['success']
и равен ли его значение 1
, затем выведите сообщение об успехе. Посетитель может перезагружать эту страницу снова и снова – и ничего не будет отправлено повторно.

К сожалению, это не сработало, и я не понимаю почему, потому что этот php-код действительно выполняется (просто чтобы подтвердить - мне нужно было только заменить echo?

Вы должны отправить заголовок до того, как какой-либо вывод будет отправлен в браузер.

@ameeromar Да. Вся обработка данных должна быть выполнена до начала вывода.

Это работает в WP, и 303 — правильный код редиректа в данном случае.

Основная идея заключается в перенаправлении пользователя на другие страницы после отправки формы, что предотвратит повторную отправку формы при обновлении страницы. Однако, если вам нужно оставить пользователя на той же странице после отправки формы, это можно сделать несколькими способами.
Очистка данных формы
Один из способов предотвратить повторную отправку формы при обновлении страницы — это очистить данные формы после их отправки, чтобы переменная, хранящая данные формы, стала пустой. Затем оберните блок кода обработки формы проверкой на пустоту формы.
if(!empty($_POST) && $_SERVER['REQUEST_METHOD'] == 'POST'){ $data = // код обработки здесь unset $data; }
Это приведет к тому, что переменная $data станет пустой после обработки, и первое условие предотвратит повторную отправку формы при обновлении страницы.
Javascript
Этот метод довольно прост и блокирует всплывающее окно с запросом повторной отправки формы при обновлении после отправки формы. Просто поместите эту строку javascript-кода в подвал вашего файла и увидите результат.
<script> if ( window.history.replaceState ) { window.history.replaceState( null, null, window.location.href ); } </script>
Больше информации по таким запросам вы можете найти по этой ссылке.

У меня была такая же проблема, которая усложнялась тем, что я перенаправляю все URL в один файл .php. Оказалось, что для решения достаточно вставить следующий фрагмент кода перед выводом любого HTML на страницу.
<?php
if (isset($_POST['mypostvar']) && isset($_SERVER['REQUEST_URI']))
{
[обработать POST-данные в 'mypostvar']
header ('Location: ' . $_SERVER['REQUEST_URI']);
exit();
}
?>
Это перенаправит на ту же страницу после обработки POST-данных, как вам и нужно. После перенаправления исходные POST-данные исчезнут и не будут вызывать повторную отправку. Функция 'header()' будет работать только если вы вставите её до вывода любого содержимого на страницу. exit() обязателен.
Вы должны обработать POST-данные до вызова header().

Я решил эту проблему, используя действие template_redirect (либо в плагине, либо в файле functions.php вашей темы).
add_action('template_redirect','myfunction') ;
function myfunction() {
global $post;
$post_id = $post->ID;
if ( isset( $_POST['html-upload'] ) && !empty( $_FILES ) ) {
require_once(ABSPATH . 'wp-admin/includes/admin.php');
$id = media_handle_upload('async-upload', $post_id); // ID поста страницы "Файлы клиента"
unset($_FILES);
if ( is_wp_error($id) ) {
$errors['upload_error'] = $id;
$id = false;
}
}
$error = ($errors) ? 1 : 0;
wp_redirect( "/?p={$post_id}?errors={$error}",301);
}
Затем на вашей странице вы можете проверить наличие ошибок
if ($_GET['errors']) {
echo "<p>Произошла ошибка при загрузке вашего файла.</p>";
} else {
echo "<p>Ваш файл успешно загружен.</p>";
}
(Я не тестировал этот код.. но он должен дать вам хорошую отправную точку).

Более простой способ — удалить действие из формы и использовать скрытое поле action. Например:
<html>
<form action="" method="post"><input type="text" name="name" />
<input type="submit" value="Отправить" />
<input type="hidden" name="action" value="Submit" />
</form>
</html>
В контроллере проверяйте валидность и отправку формы, чтобы определить, была ли она отправлена:
<?php
if (isset($_POST['action']) && $_POST['action'] == 'Submit'){
// здесь следует добавить код для валидации ввода пользователя
// если всё в порядке, отправляем форму
header('Location: .'); // перенаправляет на контроллер без повторной отправки
}
?>
Этот метод очень полезен для скриптов, где вы добавляете или удаляете записи на административной странице, так как он перезагружает страницу без повторной отправки, и удалённая или добавленная запись будет соответственно отражена на странице :)

Лучший метод, который я нашел, это использование JavaScript и CSS. Обычный метод перенаправления в PHP header('Location: <a href="a0">http://www.yourdomain.com/url</a>);
будет работать, но он вызывает предупреждение "Warning: Cannot modify header information - headers already sent" в различных фреймворках и CMS, таких как WordPress, Drupal и других. Поэтому я предлагаю использовать следующий код:
echo '<style>body{display:none;}</style>';
echo '<script>window.location.href = "http://www.siteurl.com/mysuccesspage";</script>';
exit;
Тег <style>
важен, иначе пользователь может почувствовать, что страница загрузилась дважды. Если мы используем стиль с body {display: none;}
и затем обновляем страницу, то пользовательский опыт будет таким же, как при использовании header('Location: ....);
в PHP.
Надеюсь, это поможет :)

Решение 1:
Если вы добавляете запись в тип записи, просто сгенерируйте случайный код с помощью PHP-функции rand()
и сохраните этот код при добавлении записи. Также установите тот же код в переменную $_POST['uniqueid']
.
Затем при добавлении проверьте, существует ли текущий uniqueid в записях или нет, это можно сделать с помощью wp_query()
.
Решение 2: Перенаправьте на другую страницу с помощью JavaScript. Однако учтите, что пользователь может вернуться назад и при обновлении страницы запись снова сохранится. Для этой проблемы первое решение будет оптимальным.
Решение 3: Используйте AJAX для добавления записи — тогда таких проблем не возникнет. Но если вам важны просмотры страниц, это не лучшая идея, разве что для Google Adsense.
Я просто попытался помочь, исходя из своего опыта. Если кому-то нужен код для решения проблемы, просто спросите — я поделюсь.

Простой и легкий способ сделать это в PHP. Пример ниже:
Не забудьте HTML-теги (эта форма не позволяет их использовать здесь, поэтому я использую [это])
$firstname = $post[firstname]
$lastname = $post[lastname]
[form action="here.php" method="post"]
Имя [input type='firstname' name='firstname']
Фамилия [input type='text' name='lastname']
[input type=submit value=Отправить]
[/form]
if($firstname==""||$lastname=="")
{
echo "Имя и фамилия не заполнены";
}
else
{
mysql_query("ВАШ ЗАПРОС НА ВСТАВКУ В БАЗУ ДАННЫХ ЗДЕСЬ");
header("Location:here.php");
}
Вот как сохранить данные в базе данных и избежать повторной отправки одних и тех же данных при обновлении страницы
