Вопрос или проблема
Я пытаюсь изучить PHP, создавая относительно простое приложение на WordPress, это базовая CRM, и у меня уже есть неплохой прогресс, но я застрял на некоторых тонкостях.
У меня возникли серьезные проблемы с ‘headers already sent’ при попытке заставить работать wp_redirect() после создания нового клиента пользователем.
Вот пример того, что я хочу сделать:
-
/new-customer.php : Создать новый Пользовательский Тип Записи через фронтенд и затем перенаправить на страницу одного поста этого клиента. Вот код:
<?php $address_line_1 = $_POST['address_line_1']; $address_line_2 = $_POST['address_line_2']; $suburb = $_POST['suburb']; $state = $_POST['state']; $post_code = $_POST['post_code']; $country = $_POST['country']; $email = $_POST['email']; $first_name = $_POST['first_name']; $last_name = $_POST['last_name']; $phone_number = $_POST['phone_number']; $progress_identifier="1"; // ОБРАБОТКA ФОРМЫ if ('POST' == $_SERVER['REQUEST_METHOD'] && !empty($_POST['action']) && $_POST['action'] == "new_customer") { $new_customer = array( 'post_title' => wp_rand(100,999).'-'.wp_rand(), 'post_author' => $user_ID, 'post_status' => 'publish', 'post_type' => 'customer' ); $pid = wp_insert_post($new_customer); add_post_meta($pid, 'address_line_1', $address_line_1, true); add_post_meta($pid, 'address_line_2', $address_line_2, true); add_post_meta($pid, 'suburb', $suburb, true); add_post_meta($pid, 'state', $state, true); add_post_meta($pid, 'post_code', $post_code, true); add_post_meta($pid, 'country', $country, true); add_post_meta($pid, 'email', $email, true); add_post_meta($pid, 'first_name', $first_name, true); add_post_meta($pid, 'last_name', $last_name, true); add_post_meta($pid, 'phone_number', $phone_number, true); add_post_meta($pid, 'address', $address, true); add_post_meta($pid, 'progress_identifier', $progress_identifier, true); $survey_post = array( 'post_title' => $pid . '-' . wp_rand(), 'post_author' => $user_ID, 'post_status' => 'publish', 'post_type' => 'survey' ); $survey_id = wp_insert_post($survey_post); global $wpdb; $wpdb->insert( $wpdb->p2p, array( 'p2p_from' => $survey_id, 'p2p_to' => $pid, 'p2p_type' => 'survey_to_customer' ) ); wp_redirect(home_url()); exit(); } ?>
Этот код размещен после HTML-формы.
Я знаю, что wp_redirect() должно вызываться до того, как на страницу будет выведено что-либо, но я не уверен, как это сделать, потому что я пытался разместить его выше на странице, но это ни к чему не привело.
Не стесняйтесь критиковать меня за плохой код и неопределённый вопрос, но если вы можете направить меня в правильном направлении, чтобы достичь того, что я пытаюсь сделать, это было бы замечательно! Я пытался разбить все на функции, чтобы вызывать их через хук ‘save_post’, но и с этим не повезло.
Спасибо за внимание!
Вам следует оставить форму на new-customer.php и установить действие формы на POST к другому скрипту (что-то вроде new-customer-process.php), затем вставьте свой PHP-код в этот скрипт. По сути, пользователь не заметит разницы, так как его перенаправят обратно на главную страницу.
Чтобы дать вам больше информации, форма отправляет заголовки, и поэтому вам нужно разделить форму и скрипт обработки. Перенаправление должно происходить ДО того, как будет отправлен какой-либо HTML.
Вы должны вызвать
exit;
после wp_redirect
и вам следует сохранить данные поста в хуке pre_get_posts
.
Я бы посоветовал вам посмотреть на AJAX-вызовы WordPress.
Вы можете добавить ваш AJAX так:
add_action( 'wp_ajax_{nopriv_}new_customer', 'my_function_to_hendle_ajax' );
где {nopriv_}
предназначен для пользователей, не вошедших в систему
и ваша функция будет выглядеть так:
function my_function_to_hendle_ajax() {
$address_line_1 = $_POST['address_line_1'];
$address_line_2 = $_POST['address_line_2'];
$suburb = $_POST['suburb'];
$state = $_POST['state'];
//....
// нет необходимости в if( 'post' .... )
$new_customer = array(
'post_title' => wp_rand(100,999).'-'.wp_rand(),
'post_author' => $user_ID,
'post_status' => 'publish',
'post_type' => 'customer'
);
$pid = wp_insert_post($new_customer);
add_post_meta($pid, 'address_line_1', $address_line_1, true);
add_post_meta($pid, 'address_line_2', $address_line_2, true);
// ....
wp_redirect(home_url());
exit();
}
А ваша HTML-форма должна быть:
<form action="<?php echo admin_url( 'admin-ajax.php' ); ?>" method="POST">
<input type="hidden" name="action" value="new_customer" />
...
</form>
Кроме того, вы можете вернуть с помощью функции wp_send_json_error
ошибку, чтобы обработать ее в jQuery (но в этом случае вам нужно использовать $.ajax или $.post) при отправке формы.
Проверьте документацию о WordPress Ajax
. Надеюсь, это поможет вам.
Ответ или решение
Конечно! Понимание работы функции wp_redirect()
в WordPress очень важно, особенно когда вы работаете с пользовательскими постами (CPT) и формами на фронтенде. Основная проблема, с которой вы столкнулись, заключается в ошибке "headers already sent", которая возникает, когда вы пытаетесь отправить заголовки HTTP после того, как уже был выполнен вывод HTML-контента.
Решение проблемы с wp_redirect()
Чтобы обойти эту проблему, мы можем использовать AJAX для обработки вашей формы без необходимости перезагружать страницу и избегания ситуации с заголовками. Давайте поймём, как это сделать шаг за шагом.
- Создайте AJAX действие в WordPress
Вам нужно зарегистрировать новый AJAX обработчик в functions.php
вашей темы. Это можно сделать следующим образом:
add_action('wp_ajax_new_customer', 'my_function_to_handle_ajax');
add_action('wp_ajax_nopriv_new_customer', 'my_function_to_handle_ajax');
function my_function_to_handle_ajax() {
// Ваша логика обработки формы
if (isset($_POST['address_line_1']) && !empty($_POST['action']) && $_POST['action'] == "new_customer") {
$user_ID = get_current_user_id(); // Получаем ID текущего пользователя
$address_line_1 = sanitize_text_field($_POST['address_line_1']);
$address_line_2 = sanitize_text_field($_POST['address_line_2']);
$suburb = sanitize_text_field($_POST['suburb']);
$state = sanitize_text_field($_POST['state']);
$post_code = sanitize_text_field($_POST['post_code']);
$country = sanitize_text_field($_POST['country']);
$email = sanitize_email($_POST['email']);
$first_name = sanitize_text_field($_POST['first_name']);
$last_name = sanitize_text_field($_POST['last_name']);
$phone_number = sanitize_text_field($_POST['phone_number']);
// Создание нового заказчика
$new_customer = array(
'post_title' => wp_rand(100, 999) . '-' . wp_rand(),
'post_author' => $user_ID,
'post_status' => 'publish',
'post_type' => 'customer'
);
$pid = wp_insert_post($new_customer);
// Добавление метаданных
add_post_meta($pid, 'address_line_1', $address_line_1, true);
add_post_meta($pid, 'address_line_2', $address_line_2, true);
add_post_meta($pid, 'suburb', $suburb, true);
add_post_meta($pid, 'state', $state, true);
add_post_meta($pid, 'post_code', $post_code, true);
add_post_meta($pid, 'country', $country, true);
add_post_meta($pid, 'email', $email, true);
add_post_meta($pid, 'first_name', $first_name, true);
add_post_meta($pid, 'last_name', $last_name, true);
add_post_meta($pid, 'phone_number', $phone_number, true);
// Ссылка для перенаправления
$redirect_url = get_permalink($pid); // Получение URL для перенаправления
// Отправка ответа с перенаправлением
wp_send_json_success(array('redirect' => $redirect_url));
} else {
wp_send_json_error('Invalid request');
}
}
- Измените вашу HTML-форму для использования AJAX
Вместо отправки данных формы через стандартный метод POST, давайте используем AJAX. Ваш код формы может выглядеть следующим образом:
<form id="new-customer-form" method="post">
<input type="text" name="address_line_1" required />
<input type="text" name="address_line_2" required />
<input type="text" name="suburb" required />
<input type="text" name="state" required />
<input type="text" name="post_code" required />
<input type="text" name="country" required />
<input type="email" name="email" required />
<input type="text" name="first_name" required />
<input type="text" name="last_name" required />
<input type="text" name="phone_number" required />
<input type="hidden" name="action" value="new_customer" />
<button type="submit">Создать клиента</button>
</form>
- Добавьте JavaScript для обработки отправки формы
Теперь добавим JavaScript, который будет перехватывать отправку формы и отправлять данные с помощью AJAX:
jQuery(document).ready(function($) {
$('#new-customer-form').on('submit', function(e) {
e.preventDefault(); // предотвращаем стандартную отправку формы
$.ajax({
url: '<?php echo admin_url('admin-ajax.php'); ?>',
type: 'POST',
data: $(this).serialize(), // сериализуем данные формы
success: function(response) {
if (response.success) {
window.location.href = response.data.redirect; // перенаправление
} else {
alert('Произошла ошибка: ' + response.data); // обработка ошибки
}
},
error: function(xhr, status, error) {
alert('Ошибка: ' + error); // обработка ошибок AJAX
}
});
});
});
Заключение
Таким образом, мы избегаем проблемы с заголовками, обрабатывая отправку формы с помощью AJAX. Это позволяет вам перенаправлять пользователей на нужную страницу после успешного создания нового клиента, не сталкиваясь с ошибками, связанными с выводом данных на экран до вызова wp_redirect()
. Убедитесь, что ваш JavaScript подключен корректно, и ваша форма работает как нужно. Надеюсь, это поможет вам в разработке вашего приложения на базе WordPress!