Не передаётся корректно action при AJAX.
Не получается сделать ajax-запрос.
Стоит задача сделать калькулятор калорий и индекса массы тела. Расчёты производятся в бэкенде в плагине, фронт js передаёт данные из формы.
HTML:
<form action="bmi" class="calculator__form" id="calcForm" method="POST"> <input type="text" name="height" class="calculator__input input__height" placeholder="Введите ваш рост (см)"> <input type="text" name="weight" class="calculator__input input__weight" placeholder="Введите ваш вес (кг)"> <input type="text" name="age" class="calculator__input input__age" placeholder="Введите ваш возраст"> <select name="gender" id="" class="calculator__input input__gender"> <option value="choose">Выберите ваш пол</option> <option value="male">Мужчина</option> <option value="female">Женщина</option> </select> <select name="activity" id="" class="calculator__input input__activity"> <option value="choose">Выберите ваш уровень активности</option> <option value="1-to-3">Тренировки 1-3 раза в неделю</option> <option value="3-to-5">Тренировки 3-5 дней в неделю</option> <option value="sportsman">Спортсмены, тренировки чаще 1 раза в день</option> </select> </form>
JS-код:
'use strict';
let calcForm = document.querySelector('#calcForm');
calcForm.addEventListener('submit', function (e) {
e.preventDefault();
let data = {
'action': 'bmi',
'height': +document.querySelector('input[name="height"]').value,
'weight': +document.querySelector('input[name="weight"]').value,
'age': +document.querySelector('input[name="age"]').value,
'gender': document.querySelector('select[name="gender"]').value,
'activity': document.querySelector('select[name="activity"]').value
}
let xhr = new XMLHttpRequest();
xhr.open('POST', myAjax.ajaxurl, true);
xhr.responseType = 'json';
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
xhr.send(JSON.stringify(data));
xhr.addEventListener('load', () => {
console.log(xhr.response);
});
});
PHP-код в плагине:
<?php
/*
Plugin Name: bmi
*/
add_action( 'wp_ajax_bmi', 'count_bmi' );
add_action( 'wp_ajax_nopriv_bmi', 'count_bmi' );
add_action( 'wp_enqueue_scripts', 'include_bmi_scripts' );
function count_bmi() {
$height = $_POST['height'];
$weight = $_POST['weight'];
$age = $_POST['age'];
$gender = $_POST['gender'];
$activity = $_POST['activity'];
$bmi = 0;
$bmr = 0;
$bmra = 0;
$message = "";
$image = "";
$bmi = $weight / (($height / 100) * ($height / 100));
if ($gender == 'male') {
$bmr = 88.36 + (13.4 * $weight) + (4.8 * $height) - (5.7 * $age);
} else {
$bmr = 447.6 + (9.2 * $weight) + (3.1 * $height) - (4.3 * $age);
}
if ($activity == 'desk') {
$bmra = $bmr * 1.2;
} else if ($activity == '1-to-3') {
$bmra = $bmr * 1.375;
} else if ($activity == '3-to-5') {
$bmra = $bmr * 1.55;
} else if ($activity == '6-to-7') {
$bmra = $bmr * 1.725;
} else if ($activity == 'sprotsman') {
$bmra = $bmr * 1.9;
} else {
$bmra = 0;
}
$out = array (
'message' => $message,
'bmi' => $bmi,
'bmr' => $bmr,
'bmra' => $bmra
);
header('Content Type: text/json; charset=utf-8');
echo json_encode($out);
}
function include_bmi_scripts() {
wp_enqueue_script('bmi-js', plugins_url( 'bmi.js', __FILE__ ), array(), false, true);
wp_localize_script('bmi-js', 'myAjax', array('ajaxurl'=>admin_url('admin-ajax.php')));
}
JS-скрипт отрабатывает корректно ровно до того момента, как вызывается метод send() у объекта класса XMLHttpRequest.
Если поменять myAjax.ajaxurl на сторонний фейковый api url, то приходят корректные ответы от сервера и возвращаются нужные данные. Но как только дело доходит до отправки запроса в admin-ajax.php, то вылазит 400-я ошибка, а сервер возвращает 0.
Я посмотрел код и знаю, что 0 возвращается в случае некорректного action либо его отсутствия. Но как мне ещё его передать, я ума не приложу. Я пробовал добавлять его в url (myAjax.ajaxurl + '?action=bmi') - не работает; я пробовал передавать не json, а FormData (но у меня почему-то данные туда даже аппендиться не хотели, после всех append оставался пустой объект). И что я только не делал, но результат всё равно один и тот же.
Вопрос: где я косячу? Как мне передать action при помощи чистого js?
P.S. fetch тоже пробовал, не хочет работать. Сделать хочу именно на чистом js, чтобы понимать по шагам, что происходит вообще и не быть завязанным на фреймворки.
Оставлю на всякий случай ссылку на форум. Задавал там свой вопрос, можно прочитать уже данные мне советы, что я там пробовал и какие были результаты, чтобы не тратить время впустую. А перепробовал реально много чего.
P.S. делаю на виртуальном сервере xampp.
https://www.cyberforum.ru/wordpress/thread2999829.html
Там пример есть
Для начала отправьте простой запрос:
let xhr = new XMLHttpRequest(); let url = myAjax.ajaxurl+ '?action=bmi'; alert( url ); // проверка, а куда отправляем данные? xhr.open( 'POST', url, true ); xhr.addEventListener('load', () => { console.log(xhr.response); });function count_bmi() { print_r( $_POST ); exit; // ... }Это не работает. Я пробовал экшн передавать по ссылке - 500 ошибка выскакивает. Урл правильный, отправляет в /wp-admin/admin-ajax.php.
https://stackoverflow.com/questions/9713058/send-post-data-using-xmlhttprequest
вот там РАБОЧИЙ пример.
let xhr = new XMLHttpRequest(); let url = ajaxurl + '?action=bmi'; let params = 'orem=ipsum&name=binny'; xhr.open("POST", url, true); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.send(params); xhr.addEventListener('load', () => { console.log(xhr.response); });Код проверил локально - и он работает.
Как получить в таком виде переменную params - уже сами разберетесь.
ЗАМЕЧУ: если у вас при базовом запросе НЕТ вообще ответа от сервера - значит вы НЕ отправляете туда запрос.
У меня при неправ передаче данных - в $_POST был пустой массив.
У вас же - как вы пишите, вообще сервер НЕ отвечает, что есть бредом.
Значит вы не отправл туда, а именно на admin-ajax.php данные ИЛИ они блокируются кем-то чем-то.
Базово все работает "с коробки".
Во-первых вместо
должно быть
Во-вторых вместо
header('Content Type: text/json; charset=utf-8'); echo json_encode($out);есть нативный вордпресовский вывод
Пробовал и JSON.stringify, и просто data, и FormData отправлять. Не работает. Пробовал через fetch и jquery отправлять. На сторонних апишках всё ок, отрабатывает корректно, но как только дело касается вордпресса, то он почему-то не видит экшн. Попытка передать его через урл тоже ни к чему не привела.
Насчёт вордпрессовского родного вывода - не знал. Спасибо. Делал многое по ютубу и гуглу, видел там реализацию, которая у меня сейчас.
Вы так и не отписали, вы заменили ли код в обоих местах и что теперь получается?
Проблема в том что ваш код
header('Content Type: text/json; charset=utf-8'); echo json_encode($out);должен иметь третью строчку
именно из-за этого у вас 400 с выводом 0
Всё равно 400-я ошибка. Фишка там даже не в php-коде, почему-то admin-ajax.php просто не видит action. А если ему его передавать насильно ссылкой, то 500-я ошибка вообще вылазит
Как вам уже написал уважаемый Stepan, допишите в вашей функции хука в самом начале
function count_bmi() { echo json_encode( $_POST );и посмотрите что возвращает в ответе в консоле.
А в JS допишите здесь после 'use strict'
Нужно посмотреть все ли там правильно.