Как предотвратить повторную отправку формы при обновлении страницы

20 апр. 2013 г., 18:27:44
Просмотры: 103K
Голосов: 9

Привет! У меня есть форма, которая добавляет вложения к записи, однако когда форма отправляется, она просто выводит "ваш файл был загружен", не показывая запись с новым вложением. Когда пользователь обновляет страницу (чтобы увидеть новое вложение), форма отправляется снова!

Возможно ли либо (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>

Спасибо! :)

0
Все ответы на вопрос 9
5
12

Вместо …

} 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, затем выведите сообщение об успехе. Посетитель может перезагружать эту страницу снова и снова – и ничего не будет отправлено повторно.

20 апр. 2013 г. 18:34:57
Комментарии

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

ameeromar ameeromar
20 апр. 2013 г. 19:40:33

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

fuxia fuxia
20 апр. 2013 г. 19:42:06

Значит, нужно поместить этот php-код в заголовок?

ameeromar ameeromar
26 апр. 2013 г. 16:02:14

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

fuxia fuxia
26 апр. 2013 г. 16:12:29

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

skobaljic skobaljic
29 авг. 2021 г. 17:09:54
1

Основная идея заключается в перенаправлении пользователя на другие страницы после отправки формы, что предотвратит повторную отправку формы при обновлении страницы. Однако, если вам нужно оставить пользователя на той же странице после отправки формы, это можно сделать несколькими способами.

Очистка данных формы

Один из способов предотвратить повторную отправку формы при обновлении страницы — это очистить данные формы после их отправки, чтобы переменная, хранящая данные формы, стала пустой. Затем оберните блок кода обработки формы проверкой на пустоту формы.

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>

Больше информации по таким запросам вы можете найти по этой ссылке.

11 мая 2018 г. 11:54:20
Комментарии

Ваш javascript сработал, но я хочу разобраться с php, как сохранить код обработки в переменную?

Enjabain Enjabain
13 мая 2023 г. 14:55:53
0

У меня была такая же проблема, которая усложнялась тем, что я перенаправляю все 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().

12 сент. 2013 г. 02:41:14
1

Я решил эту проблему, используя действие 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>";
}

(Я не тестировал этот код.. но он должен дать вам хорошую отправную точку).

12 сент. 2013 г. 04:33:37
Комментарии

С global $post в первой строке, шансы что эта функция заработает увеличатся...

gmazzap gmazzap
12 сент. 2013 г. 05:40:44
0

Вы также можете проверить $_SERVER['REQUEST_METHOD'] === 'POST', чтобы убедиться, что страница была обновлена методом POST перед обработкой формы.

if ( $_SERVER['REQUEST_METHOD'] === 'POST' )
{
   // Выполняем действия
}
13 сент. 2013 г. 01:40:02
0

Более простой способ — удалить действие из формы и использовать скрытое поле 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: .'); // перенаправляет на контроллер без повторной отправки
}
?>

Этот метод очень полезен для скриптов, где вы добавляете или удаляете записи на административной странице, так как он перезагружает страницу без повторной отправки, и удалённая или добавленная запись будет соответственно отражена на странице :)

10 янв. 2016 г. 00:06:52
0

Лучший метод, который я нашел, это использование 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.

Надеюсь, это поможет :)

23 июн. 2017 г. 15:33:06
0

Решение 1: Если вы добавляете запись в тип записи, просто сгенерируйте случайный код с помощью PHP-функции rand() и сохраните этот код при добавлении записи. Также установите тот же код в переменную $_POST['uniqueid'].

Затем при добавлении проверьте, существует ли текущий uniqueid в записях или нет, это можно сделать с помощью wp_query().

Решение 2: Перенаправьте на другую страницу с помощью JavaScript. Однако учтите, что пользователь может вернуться назад и при обновлении страницы запись снова сохранится. Для этой проблемы первое решение будет оптимальным.

Решение 3: Используйте AJAX для добавления записи — тогда таких проблем не возникнет. Но если вам важны просмотры страниц, это не лучшая идея, разве что для Google Adsense.

Я просто попытался помочь, исходя из своего опыта. Если кому-то нужен код для решения проблемы, просто спросите — я поделюсь.

1 мая 2020 г. 01:05:04
0
-2

Простой и легкий способ сделать это в 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");

}

Вот как сохранить данные в базе данных и избежать повторной отправки одних и тех же данных при обновлении страницы

7 дек. 2014 г. 17:14:57