Кастомный PHP эндпоинт для AJAX вызова в WordPress плагине
Я впервые пишу плагин и столкнулся с проблемой.
Я использую AJAX в своем плагине. Мой JavaScript файл находится в папке ../wp-content/plugins/myplugin/js/
, и в нем я пытаюсь вызвать PHP файл, который расположен в ../wp-content/plugins/myplugin/
jQuery.ajax({
url: "/wp-content/plugins/myplugin/myfile.php?myparam=" + myparam,
context: document.body
});
Мой вопрос: Как сделать эту ссылку рабочей независимо от того, где пользователь установил плагин.
Потому что если, например, пользователь установит плагин в http://localhost/subdir/
, ссылка будет некорректной.
Можно ли как-то создать относительную ссылку?

Прежде всего, не следует вызывать собственный PHP файл напрямую. Вместо этого следует использовать конечную точку admin-ajax
. Документация
В административной части сайта можно использовать переменную ajaxurl для получения URL для AJAX запросов. На фронтенде вам необходимо самостоятельно объявить переменную с URL. Это описано в документации:
Примечание: В отличие от административной части, глобальная переменная ajaxurl не определяется автоматически на фронтенде, если у вас не установлен BuddyPress или другой плагин, использующий AJAX. Вместо того чтобы полагаться на глобальную переменную, объявите пространство имен JavaScript с собственным свойством ajaxurl. Также можно использовать wp_localize_script() для предоставления URL вашему скрипту, сгенерировав его с помощью выражения: admin_url( 'admin-ajax.php' )
Данное решение должно устранить проблему:
add_action( 'wp_head', 'front_ajaxurl' );
function front_ajaxurl() {
wp_register_script( 'admin_ajax_front', plugin_dir_url(__FILE__) . 'script.js' );
$translation_array = array(
'ajaxurl' => admin_url( 'admin-ajax.php' )
);
wp_localize_script( 'admin_ajax_front', 'front', $translation_array );
wp_enqueue_script( 'admin_ajax_font', false, array(), false, true ); // последний параметр true добавит скрипт в подвал
}
Затем в вашем JS файле:
$.ajax({
url: front.ajaxurl,
...
})

Смешивание JavaScript и PHP кода — не лучшая практика. Как указано в цитате из документации, я бы рекомендовал использовать wp_localize_script()
. Это гарантирует, что переменная будет определена до загрузки скрипта, который от нее зависит.

Еще лучше, чем wp_localize_script()
, вы можете использовать wp_add_inline_script()
, начиная с WordPress 4.5. Эта функция позволяет выводить встроенные скрипты в рамках мощной системы управления зависимостями WordPress, и не ограничивается только JavaScript объектом, как wp_add_inline_script()
.

Я все еще не понимаю... Я до сих пор не знаю, как мне ссылаться на myfile.php и где? Нужно ли превращать его в функцию или как? Пожалуйста, дайте подсказку, я запутался.

Если вам действительно нужно вызвать файл из вашего плагина, вы можете сделать это с помощью plugin_dir_url(__FILE__)

Я новичок, но у меня сработало
Добавьте следующее в functions.php. Обратите внимание, что 'wp_ajax' — это префикс по соглашению, а 'do_something' — произвольно выбранное мной имя действия:
add_action( 'wp_ajax_do_something', 'do_something' );
function do_something() {
//действительно, вперед, сделайте что-нибудь
die("верните что-нибудь");
}
Чтобы сделать AJAX-запрос из браузера (на стороне клиента), я смог найти конечную точку, используя wp.ajax.settings.url
. Глобальная переменная wp
определена в объекте window.
//do_something здесь должно соответствовать указанному выше, вы можете добавить другие параметры в этот объект
var data = { action: 'do_something' };
jQuery.post(wp.ajax.settings.url, data, function(response) {
console.log('Результат: ' + response);
});
У меня установлен WordPress 4.6.1 (последняя версия на момент написания) и несколько плагинов. Я ссылался на эту документацию, где ошибочно указано, что ajaxurl определен, но в моем случае это не так: https://codex.wordpress.org/AJAX_in_Plugins

Я столкнулся с такой же проблемой.
Я хотел использовать свой собственный endpoint вместо admin-ajax, потому что у меня есть правила перезаписи, которые заполняют все переменные, необходимые для выполнения ajax-действий.
Таким образом, использование (как указано в codex)
jQuery(document).ready(function($) {
var data = {
'action': 'my_action',
'whatever': ajax_object.we_value // Передаем PHP-значения по-другому!
};
jQuery.post(ajax_object.ajax_url, data, function(response) {
alert('Получено от сервера: ' + response);
});
});
и
add_action( 'wp_ajax_my_action', 'my_action' );
add_action( 'wp_ajax_nopriv_my_action', 'my_action' );
только усложняет мой код.
В итоге я сделал так, и это работает:
jQuery.ajax({
type: "post",
url: MYCUSTOMENDPOINT?ajax_action,
dataType: 'json',
...
в сочетании с:
add_action( 'init', 'rewrite_rules');
add_filter( 'template_include','handle_ajax_action');
function rewrite_rules(){
add_rewrite_tag(
'%ajax_action%',
'([^&]+)'
);
}
function handle_ajax_action($template){
$success = null;
// Поскольку переменная запроса "ajax" не требует значения, нужно проверить ее наличие
if ( !$action = get_query_var( 'ajax_action' ) ) return $template; // ajax-действие отсутствует
$result = array(
'input' => $_REQUEST,
'message'=> null,
'success'=> null,
);
$success = ...
if ( is_wp_error($success) ){
$result['success'] = false;
$result['message'] = $success->get_error_message();
}else{
$result['success'] = $success;
}
header('Content-type: application/json');
send_nosniff_header();
header('Cache-Control: no-cache');
header('Pragma: no-cache');
wp_send_json( $result );
}
