Ошибка "headers already sent" при использовании wp_redirect после формы отправки на фронтенде
Я пытаюсь создать форму для отправки постов через фронтенд и получаю следующую ошибку:
Warning: Cannot modify header information - headers already sent by (output started at /home/sadlight/public_html/members/wp-content/themes/default-child/announcement-submit.php:1) in /home/sadlight/public_html/members/wp-includes/pluggable.php on line 876
announcement-submit.php - это мой шаблон, приведенный ниже.
Я пробовал это решение, но безрезультатно.
Также, когда я использую wp_redirect в моем коде ниже, он вставляет ДВА поста вместо одного. Когда я удаляю его, добавляется только один пост. Любая помощь будет очень полезна!
Дополнительная информация: я использую Buddypress с темой по умолчанию Buddypress.
<?php
/*
* Шаблон: Announcement Submit
*/
$postTitleError = '';
if ( isset( $_POST['submitted'] ) ) {
if ( trim( $_POST['postTitle'] ) === '' ) {
$postTitleError = 'Пожалуйста, введите заголовок.';
$hasError = true;
}
}
get_header(); ?>
<div id="content">
<div class="padder">
<form action="" id="primaryPostForm" method="POST">
<fieldset>
<label for="postTitle"><?php _e('Заголовок поста:', 'framework') ?></label>
<input type="text" name="postTitle" id="postTitle" class="required" value="<?php if ( isset( $_POST['postTitle'] ) ) echo esc_attr( stripslashes( $_POST['postTitle'] ) ); ?>" />
</fieldset>
<fieldset>
<?php wp_editor( 'Тестовый контент', 'postcontent'); ?>
</fieldset>
<fieldset>
<?php wp_nonce_field( 'post_nonce', 'post_nonce_field' ); ?>
<input type="hidden" name="submitted" id="submitted" value="true" />
<button type="submit"><?php _e('Добавить пост', 'framework') ?></button>
</fieldset>
</form>
<?php if ( $postTitleError != '' ) { ?>
<span class="error"><?php echo $postTitleError; ?></span>
<div class="clearfix"></div>
<?php } ?>
<?php
if ( isset( $_POST['submitted'] ) && isset( $_POST['post_nonce_field'] ) && wp_verify_nonce( $_POST['post_nonce_field'], 'post_nonce' ) ) {
if ( trim( $_POST['postTitle'] ) === '' ) {
$postTitleError = 'Пожалуйста, введите заголовок.';
$hasError = true;
}
$post_information = array(
'post_title' => wp_strip_all_tags( $_POST['postTitle'] ),
'post_content' => wp_kses_post( $_POST['postcontent'] ),
'post_type' => 'post',
'post_status' => 'pending'
);
wp_insert_post( $post_information );
}
$post_id = wp_insert_post( $post_information );
if ( $post_id ) {
wp_redirect( home_url() );
exit;
}
?>
</div><!-- .padder -->
</div><!-- #content -->
<?php get_sidebar(); ?>
<?php get_footer(); ?>

Как отметил Отто, вы отправляете данные в браузер перед вызовом wp_redirect()
.
get_header()
выводит HTML<head>
страницы- Вы выводите всю форму на страницу перед её обработкой.
Чтобы исправить проблему "headers already sent", вам нужно переместить всю обработку формы из нижней части страницы в её начало. Если вам нужно вызвать wp_redirect()
, этот вызов должен быть сделан до вывода чего-либо - HTML или другого содержимого - на страницу.
Что касается дублирования записи, у вас дважды вызывается wp_insert_post()
в коде:
if ( isset( $_POST['submitted'] ) && isset( $_POST['post_nonce_field'] ) && wp_verify_nonce( $_POST['post_nonce_field'], 'post_nonce' ) ) {
if ( trim( $_POST['postTitle'] ) === '' ) {
$postTitleError = 'Пожалуйста, введите заголовок.';
$hasError = true;
}
$post_information = array(
'post_title' => wp_strip_all_tags( $_POST['postTitle'] ),
'post_content' => wp_kses_post( $_POST['postcontent'] ),
'post_type' => 'post',
'post_status' => 'pending'
);
wp_insert_post( $post_information );
}
$post_id = wp_insert_post( $post_information );
Таким образом, вы пытаетесь вставить запись при каждой загрузке страницы, но если ничего не отправлено, переменная $post_information
не будет установлена и ничего не вставится. Однако при отправке формы вы создаёте новую запись как внутри проверки условия, так и за её пределами.

Кроме того, лучше перенести всю обработку формы в файл функций и подключиться к какому-нибудь хуку, например template_redirect
, где вы уверены, что ничего еще не было отправлено в браузер.

Спасибо! Это именно то, что я бы предпочел сделать для разделения логики. Однако последний час я пытаюсь лучше понять, как использовать template_redirect или что он вообще делает. Я в замешательстве.

заголовки уже отправлены (вывод начат в /home/sadlight/public_html/members/wp-content/themes/default-child/announcement-submit.php:1)
Сообщение об ошибке точно указывает на проблему.
Файл "announcement-submit.php" - это место, где возникла проблема.
Цифра "1" указывает на номер строки с ошибкой.
Это означает, что у вас есть что-то перед начальной строкой <?php
, что вызывает вывод. Возможно, это пустая строка. Или, возможно, BOM UTF-8.
Откройте файл в простом текстовом редакторе. Ничего сложного. Например, в Блокноте или VIM. Убедитесь, что перед открывающим тегом PHP ничего нет. Сохраните файл. Или в настройках сохранения вашего редактора убедитесь, что не установлена опция сохранения BOM (маркера порядка байтов) в начале файла.

Это не просто пробел перед открывающим тегом <?php
, тут весь get_header
и разметка, которая выводится перед строкой wp_redirect
в середине шаблона.

Спасибо за ответ. Я попробовал ваш совет, используя просто блокнот. Я даже убедился, что Notepad++ (мой редактор кода) сохраняет в UTF-8 без BOM. Перезагрузил файл... и теперь получаю эту ошибку: Warning: Cannot modify header information - headers already sent by (output started at /home/sadlight/public_html/members/wp-content/plugins/buddypress/bp-themes/bp-default/header.php:2) in /home/sadlight/public_html/members/wp-includes/pluggable.php on line 876
.... Строка 2 в header.php это <html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>

@Milo Я удалил все пробелы, которые мог, там где это было логично... между строками и после строк. Та же ошибка.

Это может иметь несколько причин. Заголовки могут быть отправлены только в том случае, если перед ними нет никакого вывода. Под выводом я подразумеваю любой вывод. То есть не должно быть пробелов перед открывающими тегами PHP, никаких echo
, никаких символов BOM.
По сути, это сообщение об ошибке точно указывает, где начался вывод, а значит, именно там происходит одна из вышеперечисленных проблем.
Для полного списка вещей, которые следует проверить, а также способов предотвратить эту ошибку, ознакомьтесь с этим полезным постом на Stack Overflow.
