Правильный способ передачи переменных запроса в AJAX с использованием ajaxurl
Хорошо, я не знал, как озаглавить эту тему.
Я пытаюсь переопределить стандартное поведение с помощью AJAX. Проблема здесь на самом деле не проблема, а скорее пожелание.
У меня есть этот URL:
<a href="http://example.com/?reaction=smk_remove_post&id=1226&_nonce=7be82cd4a0" class="smk-remove-post">Удалить пост</a>
В файле functions.php
у меня есть эта функция и вызов сразу после:
function smk_remove_post(){
if( !empty( $_GET['reaction'] ) && 'smk_remove_post' == $_GET['reaction'] && !empty( $_GET['id'] ) ){
if( current_user_can('edit_others_posts') && !empty($_GET['_nonce']) ){
if( wp_verify_nonce( esc_html( $_GET['_nonce'] ), 'smk_remove_post' ) ){
// Удаляем пост
wp_delete_post( absint( $_GET['id'] ), true );
}
}
}
}
smk_remove_post();
Теперь, если я кликну по ссылке, пост с ID 1226
будет удален. Все работает нормально. Задача выполнена успешно, и страница перезагружается.
Здесь мне нужен AJAX. Я хочу обработать этот URL с помощью ajax без перезагрузки страницы и получить корректный ответ.
Я добавил этот jQuery скрипт:
function smk_remove_post(){
$('.smk-remove-post').on( 'click', function( event ){
event.preventDefault();
var _this = $(this);
jQuery.ajax({
type: "GET",
url: _this.attr('href'),
success: function(response){
console.log(response);
_this.text('Все отлично, пост удален.');
}
});
});
}
smk_remove_post();
Все работает как ожидается. Пост удаляется через ajax, и страницу не нужно перезагружать. Но я не могу получить корректный ответ, вместо этого я получаю полный HTML-код текущей страницы.
Я знаю, что должен использовать admin-ajax.php
(ajaxurl), но как мне это сделать? Мне нужно отправить запрос из URL и получить ответ обратно.
Вот что я пробовал:
Я добавил это в jQuery скрипт выше:
data: {
'action': 'smk_remove_post_ajax',
},
И это в PHP:
function smk_remove_post_ajax(){
smk_remove_post();
die();
}
add_action('wp_ajax_smk_remove_post_ajax', 'smk_remove_post_ajax');
Это не работает. Вызов игнорируется, выполняется предыдущий вызов, как если бы это было сделано без ajax.
Я понимаю, что мне нужно как-то отправить запрос в admin-ajax.php, но как?
Наконец-то я разобрался.
Первой ошибкой была двойная обработка одной и той же функции. Я вызывал её один раз после объявления функции и ещё раз в ajax-действии. Поэтому при ajax-запросе функция выполнялась дважды. В примере из оригинального вопроса это не проблема, так как он упрощён и делает только одно действие, но в моём реальном коде функция выполняет гораздо больше операций, что может привести к потере нежелательных данных.
Кроме того, мне просто нужно было остановить ajax и получить кастомный ответ, ничего больше. Вот что я сделал:
1. Я изменил это:
smk_remove_post();
на это:
add_action('parse_query', 'smk_remove_post');
Лучше запускать функцию позже, когда она нужна в специальном действии.
2. Далее я модифицировал обработчик ajax:
Я удалил строку smk_remove_post();
и изменил ajax-действие с wp_ajax_smk_remove_post_ajax
на wp_ajax_smk_remove_post
:
function smk_remove_post_ajax(){
wp_die( 'ok' );
}
add_action('wp_ajax_smk_remove_post', 'smk_remove_post_ajax');
3. Я переименовал параметр запроса reaction
в action
. Изменил его в URL и функции:
4. Наконец, модифицировал jQuery-скрипт. Теперь он использует admin-ajax.php и отправляет URL как данные:
url: ajaxurl,
data: _this.attr('href'),
Вот итоговый код:
Ссылка:
<a href="http://example.com/?action=smk_remove_post&id=1226&_nonce=7be82cd4a0" class="smk-remove-post">Удалить запись</a>
PHP код:
function smk_remove_post(){
if( !empty( $_GET['action'] ) && 'smk_remove_post' == $_GET['action'] && !empty( $_GET['id'] ) ){
if( current_user_can('edit_others_posts') && !empty($_GET['_nonce']) ){
if( wp_verify_nonce( esc_html( $_GET['_nonce'] ), 'smk_remove_post' ) ){
// Удаляем запись
wp_delete_post( absint( $_GET['id'] ), true );
}
}
}
}
add_action('parse_query', 'smk_remove_post');
function smk_remove_post_ajax(){
wp_die( 'ok' );
}
add_action('wp_ajax_smk_remove_post', 'smk_remove_post_ajax');
Javascript:
function smk_remove_post(){
$('.smk-remove-post').on( 'click', function( event ){
event.preventDefault();
var _this = $(this);
jQuery.ajax({
type: "GET",
url: ajaxurl,
data: _this.attr('href').split('?')[1],
success: function(response){
console.log(response); // ok
_this.text('Всё отлично, запись удалена.');
}
});
});
}
smk_remove_post();
Примечание:
Небольшое обновление к коду выше. Для обработки параметров запроса нужно удалить путь к сайту, иначе могут возникнуть неожиданные проблемы. Я добавил это к data href
:
.split('?')[1]

Создайте ссылку следующим образом
<a href="http://example.com/?reaction=smk_remove_post&id=1226&_nonce=7be82cd4a0" data-id="1226" data-nonce="7be82cd4a0" class="smk-remove-post">Удалить запись</a>
И jQuery
$('.smk-remove-post').on( 'click', function( event ){
event.preventDefault();
var _this = $(this);
var data = {
'action': 'smk_remove_post_ajax',
'reaction': 'smk_remove_post',
'id': _this.data('id'),
'_nonce': _this.data('nonce')
};
// начиная с версии 2.8 ajaxurl всегда определен в заголовке админки и указывает на admin-ajax.php
jQuery.ajax({
type: "GET",
url: ajaxurl,
data: data,
success: function(response){
console.log(response);
_this.text('Отлично, запись удалена.');
}
});
});
См. Codex о AJAX в плагинах. И в Codex сказано:
В большинстве случаев в функции обратного вызова Ajax следует использовать wp_die(). Это обеспечивает лучшую интеграцию с WordPress и упрощает тестирование вашего кода.
Поэтому используйте wp_die();
вместо die();

Вот что я использовал раньше, но здесь мне нужно, чтобы код работал как с ajax, так и без него.

Если я отключу javascript, то произойдет откат к перезагрузке страницы, и действие будет обработано без ajax. В вашем примере это будет работать только при включенном JS.

AJAX — это не волшебство, и при запросе URL X вы получите тот же HTML для этого URL, независимо от того, делаете ли вы это из адресной строки браузера, по ссылке или через AJAX. Поэтому, если вам нужен другой ответ, отличный от HTML, вы не можете использовать тот же URL для AJAX-запроса, что и в ссылке.
WordPress имеет специальную "конечную точку" для обработки AJAX-запросов — admin-ajax.php, и все AJAX-запросы должны отправляться только на неё, примерно так: $.ajax({url:....admin-ajax.php})
Далее вам нужно сообщить WordPress, что вы хотите сделать, и для этого в запросе есть специальный параметр action
. Этот параметр определяет хук, который будет использоваться на стороне сервера для обработки запроса. В этом вопросе вы всё сделали правильно в своём коде.
Теперь вам нужны дополнительные параметры, которые идентифицируют объект, который должен быть изменён или получен в ходе AJAX-операции. Вы можете использовать постоянную ссылку (permalink) записи или её ID, например, но всё зависит от сложности операции, которую вы пытаетесь выполнить. В вашем конкретном случае, я бы предположил, что лучше всего передавать в запросе ID записи.
Как отправлять параметры? Большинство людей используют POST-запросы при работе с AJAX, но если вам нужен GET, то вы можете передать их как часть URL (что, как я предполагаю, jQuery сделает за вас).
