Расскажу про использование техники ajax в рамках движка Drupal. Начнем с теоретических моментов.
Во-первых, чтобы получить какие то данные с веб-сайта под Drupal, нужно чтобы соответствующий адрес существовал на сайте. Во-вторых, нам не хотелось бы получать данные облаченные во весь шаблон текущей темы оформления. В-третьих, надо помнить, что в drupal уже подключена библиотека jQuery, так что нам можно использовать реализацию механизма ajax в её составе.
Далее обо всем по-порядку.
Специальный раздел на сайте
Описание раздела сайта нужно начинать в рамках какого-то своего модуля. Мы будем это делать в модуле — mymodule. Надеюсь, что создавать новые модули для drupal, подключать и активировать их, вы умеете. Для каждого нового проекта я собираю все дополнительное программирование в рамках одного модуля (иногда нескольких).
Итак, мы программируем хук hook_menu.
1 2 3 4 5 6 7 8 9 10 |
/* hook menu */ function mymodule_menu() { //страница приема данных по ajax $items['ajax-request'] = array( 'page callback' => '_mymodule_ajaxcode', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items; } |
В примере мы объявили обработчик для пути сайта http://mysite.net/ajax-request — функцию — _mymodule_ajaxcode. Необходимый тип объявленного раздела — MENU_CALLBACK, который говорит drupal, что это не обычный пункт меню, а просто связка адреса (uri) и обработчика.
Далее рассмотрим примеры функций-обработчиков.
Вернуть в качестве результата ajax — код HTML
Этот случай довольно прост. Нужно в ответ на запрос, вернуть какой то HTML кусочек.
1 2 3 4 5 6 7 8 9 10 |
function _mymodule_ajaxcode() { $html_code = ''; //формируем код .... //формируем заголовки документа - указываем, что кодировка UTF8 header('Content-Type: text/html; charset=UTF-8'); echo $html_code; //конец исполнения программы exit; } |
Важно указать кодировку документа и выйти по exit. Все что вы выведите в консоль — будет результатом запроса.
Все адреса http://mysite.net/ajax-request/path1/path2/ и т.п. также будут направлены на данный обработчик. Так можно передавать параметры, читая их потом функцией arg(1), arg(2)… Никто не мешает передавать в тоже время $_POST и $_GET данные. Тут подводных камней нет.
Вернуть в качестве результата ajax — код json
В друпал встроена функция для сериализации переменных, которая пишет в формате читаемом javascript.
1 |
drupal_json_encode($var); |
1 2 3 4 5 6 7 8 9 10 |
function _mymodule_ajaxcode() { $a = array(); //формируем какие то данные в массиве $a .... //формируем заголовки документа - указываем, что кодировка UTF8 header('Content-Type: text/html; charset=UTF-8'); echo drupal_json_encode($a); //конец исполнения программы exit; } |
Вызов запроса ajax в шаблоне
Как вы убедились, со стороны сервера в drupal — всё проще пареной репы. Как организуется часть обмена данными со стороны шаблона javasctipt + HTML?
Рассмотрим незамысловатый примерчик. Будем запрашивать случайное число с сервера, по каждому нажатию на надпись «Нажми меня..».
Нам нужно запрограммировать событие — onclick, по которому будет вызываться ajax механизм. При получении данных, будем вставлять их в контейнер с id = rnd.
На сервере мы вычисляем случайное число и отправляем его как элемент массива, где вторым элементом является сообщение — «Получено случайное число».
1 2 3 4 5 6 7 8 9 10 |
function _mymodule_ajaxcode() { //читаем аргумент - максимум для случайного числа $n = arg(1) + 0; header('Content-Type: text/html; charset=UTF-8'); //возвращаем массив - // где элемент 0 - это случайное число, // а элемент 1 - строка 'Получено случайное число' echo drupal_json_encode(array(rand(0, $n), 'Получено случайное число')); exit; } |
На стороне клиента используем вот такой HTML код.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<div onclick=" $.ajax('/ajax-request/1000') //если все путем .done(function(data) { //вычисляем данные, полученные с сервера var a = eval(data); //выводим случайное число в контейнере c id = rnd $('#rnd').html(a[0]); //выводим сообщение alert(a[1]); }) //если возникает ошибка .fail(function() { alert( 'error' ); }); ">Нажми меня, чтобы получить случайное число</div> <div id="rnd"></div> |
Если есть вопросы по поводу работы функции ajax в jQuery, смотрите описание.
Здравствуйте!
Создал и подключил модуль. Сначала при нажатии на элемент возникала ошибка Uncaught TypeError: Cannot read property ‘ajax’ of undefined. Затем я поменял в обработчике onclick $.ajax на jQuery.ajax, и ошибка пропала.
Однако появилась новая: site/ajax-request/1000 404 (Not Found). И, соответственно, всплывает окно с надписью ‘error’.
Почему не находится обработчик по адресу ajax-request? Подскажите, пожалуйста, как это исправить и заставить скрипт выполняться.
Кирилл, попробуйте сбросить кеш — это делается вот тут /admin/config/development/performance. Тогда drupal подхватит новый адрес и будет выполнять маршрутизацию.
Спасибо за ответ!
К сожалению, очистка кэша не помогла — ошибка по-прежнему возникает. В чём ещё может быть причина?
Тут бы посмотреть код…
Судя по ошибке, drupal не знает адреса — /site/ajax-request/. В тексте статьи я предлагал пример с адресом /ajax-request/, возможно связано с ошибкой в HTML шаблоне? Проверьте верен ли адрес.
Довольно странно, ведь у меня всё как в примере:
Код модуля:
/* hook menu */
function mymodule_menu() {
//страница приема данных по ajax
$items[‘ajax-request’] = array(
‘page callback’ => ‘_mymodule_ajaxcode’,
‘access arguments’ => array(‘access content’),
‘type’ => MENU_CALLBACK,
);
return $items;
}
function _mymodule_ajaxcode() {
//читаем аргумент — максимум для случайного числа
$n = arg(1) + 0;
header(‘Content-Type: text/html; charset=UTF-8’);
//возвращаем массив —
// где элемент 0 — это случайное число,
// а элемент 1 — строка ‘Получено случайное число’
echo drupal_json_encode(array(rand(0, $n), ‘Получено случайное число’));
exit;
}
Код в шаблоне:
Нажми меня, чтобы получить случайное число
В комментарий всё не влезло. В общем, у меня тот же самый код, что в примере, однако почему-то адрес не находится.
Попробовал просто перейти по адресу site/ajax-request. Выдаёт ошибку 404. Может ли быть такое, что какие-то модули или настройки Drupal блокируют этот адрес? Может, его нужно зарегистрировать с помощью какой-нибудь функции или что-то вроде того?
Надо все проверить, начиная с того включен ли модуль mymodule. Раз по адресу, объявляемому в mymodule_menu() выдает ошибку 404, ясно что drupal не подключил этот адрес.
Я не знаю, что именно помогло, — повторный сброс кэша, изменение названия модуля на MyModule (чтобы совпадало с названиями функций) или же ещё что-то, но теперь всё работает.
Спасибо за помощь!