Вывести сообщение успешной отправки формы и сделать редирект. PHP
Подскажите пожалуйста, нужно при отправке форме вывести сообщение на 3 секунды и сделать редирект без js на php, почему то не происходит редирект, вот обработчик формы
$name = $_POST['name'];
$mail = $_POST['mail'];
$question = $_POST['question'];
$date = date("d/m/Y");
$add = $wpdb->insert('wp_qns', array('user_name' => $name, 'mail' => $mail, 'question' => $question, 'date' => $date), array( '%s', '%s', '%s', '%s'));
echo "Спасибо за обращение, Ваш вопрос отправлен и будет опубликован после модерации";
sleep(3);
wp_mail( '[email protected]', 'Новый вопрос!', '<span>Вам задали вопрос.<br>' .$question. '</span>');
wp_redirect('https://domen.ru/');
Ответы (1 шт):
Чтобы понять, почему так не работает, нужно знать три вещи:
- невозможно отправлять заголовки после отправки тела ответа
- ответ отправляется не сразу, а попадает в буферы - PHP имеет буфер, а также веб-сервер обычно также буферизирует данные, отправляя "все сразу" (буфер Nginx 4-8 Кб)
- заголовок
Locationпринимается браузером на исполнение сразу, без всяких пауз и выводов сообщений
Итак, разберемся.
Что такое функция wp_redirect
Функция wp_redirect(); отправляет Location - заголовок о редиректе. Браузер видит заголовок и сразу переходит. Что находится в самом ответе сервера, он не показывает (echo ... не будет выводиться в браузере).
Однако, любые заголовки невозможно отправить после отправки тела ответа. Поэтому заголовок Location PHP просто не отправляет, и об этом выводятся предупреждения, но у вас похоже, включено подавление ошибок.
Как включить вывод ошибок:
error_reporting(E_ALL);
ini_set("display_errors", 1);
Выведется:
Warning: Cannot modify header information - headers already sent by ...
Вот структура HTTP ответа, чтобы вы представляли:
заголовки (wp_redirect())
(пуста строка)
тело ответа (echo ...)
Поэтому сделать echo перед wp_redirect() нельзя. Ну, на самом деле можно, PHP обычно еще немного кеширует ответ и все-таки позволяет "вклинить" заголовки, хотя уже начал писать ответ. Как посмотреть: die(ini_get("output_buffering"));
Буфер веб-сервера
Но то, что вы хотите - показ сообщения, пауза, отправка почты, редирект - так работать не будет, потому что веб-сервер кеширует данные ответа, и отправляет большими кусками, 4-8 Кб в случае Nginx, в вашем случае - сразу одним куском. Поэтому все что происходит в промежутке echo ... sleep не будет с паузой отправлено в браузер, а попадет в буфер веб-сервера, и сразу будет отправлено по завершении скрипта. И без заголовка Location, как вы уже поняли. Но задержка в 3 секунды будет.
Решение
На самом деле, нужно просто воспользоваться другой возможностью. Отправьте в виде ответа HTML с тегом <meta http-equiv="refresh", вот пример редиректа в гугл через 3 секунды.
<meta http-equiv="refresh" content="3;url=http://www.google.com/" />
PS
В самом PHP-скрипте также может быть ob_start() (я не знаю, делает это Wordpress или нет), и тогда используется собственный буфер PHP.
Вот грубый способ выключить буфер и скинуть все данные в браузер:
// Отключаем буферизацию вывода (2)
while (ob_get_level()) {
ob_end_flush();
}