Вопрос или проблема
Я немного запутался с AJAX и пытаюсь показать посты в зависимости от действий пользователя. Сейчас у меня работает система, где пользователь выбирает категорию из выпадающего списка, и посты загружаются соответственно. Я хотел бы сделать шаг дальше и заполнить другой выпадающий список подкатегориями в зависимости от выбранной родительской категории. Посмотреть сайт можно здесь.
jQuery
$('#ajaxFilter select').on('change', function(event) {
if(event.preventDefault) { event.preventDefault(); }
$this = $(this);
$value = this.value;
$page = $this.data('page');
$term = $this.data('term');
$qty = $this.closest('#ajaxFilter').data('paged')
$params = {
//Привязка параметров
'value': $value,
'page' : $page,
'term' : $term,
'qty' : $qty,
};
//Выполнение запроса с этими параметрами
get_posts($params);
});
function get_posts($params) {
$content = $('#ajaxPosts');
$.ajax({
url: psc.ajax_url,
data: {
action: 'filter_posts',
nonce: psc.nonce,
params: $params
},
type: 'post',
dataType: 'json',
success: function(data, textStatus, XMLHttpRequest) {
if (data.status === 200) {
$content.html(data.content);
}
else if (data.status === 201) {
$content.html(data.message);
}
else {
$status.html(data.message);
}
},
error: function(MLHttpRequest, textStatus, errorThrown) {
$status.html(textStatus);
}
});
}
functions.php
function psc_filter_posts() {
if( !isset( $_POST['nonce'] ) || !wp_verify_nonce( $_POST['nonce'], 'psc' ) )
die('Доступ запрещен');
$value = intval($_POST['params']['value']);;
$term = sanitize_text_field($_POST['params']['term']);
$page = intval($_POST['params']['page']);
$qty = intval($_POST['params']['qty']);
if ( $value == 0 ) :
$tax_qry[] = [
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => $value,
'operator' => 'NOT IN'
];
else :
$tax_qry[] = [
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => $value,
];
endif;
//Настройка аргументов запроса для wp query
$args = [
'paged' => $page,
'post_status' => 'publish',
'posts_per_page' => $qty,
'tax_query' => $tax_qry
];
$qry = new WP_Query($args);
ob_start();
if ($qry->have_posts()) : ?>
have_posts()) : $qry->the_post(); ?>
LOOP STUFF
200,
'found' => $qry->found_posts
];
else :
$response = [
'status' => 201,
'message' => 'Посты не найдены'
];
endif;
$response['content'] = ob_get_clean();
die(json_encode($response));
}
add_action('wp_ajax_filter_posts', 'psc_filter_posts');
add_action('wp_ajax_nopriv_filter_posts', 'psc_filter_posts');
Эврика! В конце концов, я просто добавил второй AJAX вызов в функцию. По какой-то причине он возвращает успешный результат, но не с ответом 200. Тем не менее, это работает. Если кто-то знает, почему он возвращает неизвестный ответ (кроме 200 или 201), пожалуйста, поделитесь. Спасибо!
function get_posts($params) {
$.ajax({
url: psc.ajax_url,
data: {
action: 'get_subcats',
nonce: psc.nonce,
params: $params
},
type: 'post',
dataType: 'json',
success: function(data, textStatus, XMLHttpRequest) {
if (data.status === 200) {
}
else if (data.status === 201) {
alert('201');
$content.html(data.message);
}
else {
$('#subcategories').empty();
$('#subcategories').append(data.content);
}
},
error: function(MLHttpRequest, textStatus, errorThrown) {
$status.html(textStatus);
}
});
$.ajax({
url: psc.ajax_url,
data: {
action: 'filter_posts',
nonce: psc.nonce,
params: $params
},
type: 'post',
dataType: 'json',
success: function(data, textStatus, XMLHttpRequest) {
if (data.status === 200) {
$('#ajaxPosts').html(data.content);
}
else if (data.status === 201) {
$content.html(data.message);
}
else {
$status.html(data.message);
}
},
error: function(MLHttpRequest, textStatus, errorThrown) {
$status.html(textStatus);
}
});
}
functions.php
function psc_subcategories() {
if( !isset( $_POST['nonce'] ) || !wp_verify_nonce( $_POST['nonce'], 'psc' ) )
die('Доступ запрещен');
$value = intval($_POST['params']['value']);;
ob_start();
$categories= get_categories('child_of=".$value."&hide_empty=1');
foreach ($categories as $cat) {
$option .= '';
}
echo ''.$option;
$response['content'] = ob_get_clean();
die(json_encode($response));
}
Ответ или решение
Чтобы одновременно отправить два AJAX-запроса в WordPress, вы уже на правильном пути, добавив второй AJAX-запрос в функцию get_posts
. Однако давайте оптимизируем и структурируем ваш код, чтобы он работал надлежащим образом и не вызывал путаницы с ответами.
Шаг 1: Обновление jQuery
Вместо того чтобы вызывать два AJAX-запроса отдельно, мы объединим их, чтобы извлечь подкатегории и фильтровать посты в одном месте.
$('#ajaxFilter select').on('change', function(event) {
if(event.preventDefault) {
event.preventDefault();
}
const $this = $(this);
const $value = this.value;
const $params = {
'value': $value,
'page': $this.data('page'),
'term': $this.data('term'),
'qty': $this.closest('#ajaxFilter').data('paged'),
};
get_posts_and_subcategories($params);
});
function get_posts_and_subcategories($params) {
// Сначала получаем подкатегории
$.ajax({
url: psc.ajax_url,
data: {
action: 'get_subcats',
nonce: psc.nonce,
params: $params
},
type: 'post',
dataType: 'json',
success: function(data) {
if (data.status === 200) {
$('#subcategories').empty().append(data.content);
} else {
$('#subcategories').empty().append('<option value="-1">Нет подкатегорий</option>');
}
},
error: function() {
$('#subcategories').empty().append('<option value="-1">Ошибка загрузки подкатегорий</option>');
}
});
// Затем получаем посты
$.ajax({
url: psc.ajax_url,
data: {
action: 'filter_posts',
nonce: psc.nonce,
params: $params
},
type: 'post',
dataType: 'json',
success: function(data) {
const $content = $('#ajaxPosts');
if (data.status === 200) {
$content.html(data.content);
} else {
$content.html('<p>' + data.message + '</p>');
}
},
error: function() {
$('#ajaxPosts').html('<p>Ошибка загрузки постов</p>');
}
});
}
Шаг 2: Обновление functions.php
Вам необходимо позаботиться о том, чтобы ваш PHP код корректно обрабатывал оба AJAX-запроса. Убедитесь, что функция для получения подкатегорий функционирует правильно.
function psc_subcategories() {
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'psc'))
die('Permission denied');
$value = intval($_POST['params']['value']);
ob_start();
$categories = get_categories(['child_of' => $value, 'hide_empty' => 1]);
if ($categories) {
foreach ($categories as $cat) {
echo '<option value="' . $cat->term_id . '">' . $cat->cat_name . ' (' . $cat->count . ')</option>';
}
} else {
echo '<option value="-1">Нет подкатегорий</option>';
}
$response['content'] = ob_get_clean();
$response['status'] = 200;
die(json_encode($response));
}
add_action('wp_ajax_get_subcats', 'psc_subcategories');
add_action('wp_ajax_nopriv_get_subcats', 'psc_subcategories');
Заключение
Теперь, когда вы вызывает get_posts_and_subcategories
, два AJAX-запроса отправляются одновременно – один для получения подкатегорий, другой для загрузки постов. Это обеспечит более чистый и эффективный процесс. Если вы всё ещё получаете неожиданные ответы, убедитесь, что все возвращаемые данные правильно формируются в PHP и AJAX настроены корректно.
Данный подход позволит вам значительно улучшить интерактивность и отзывчивость вашего приложения на WordPress.