Допустим у нас есть форма и мы хотим в её интерфейс добавить какой-нибудь ajax-запрос к серверу. И Form API с его #ajax
нам не поможет, потому что запрос происходит в каком-нибудь событии из сторонней библиотеки. В общем, надо сделать сервис и обратиться к нему через $.ajax()
, или $.getJSON()
.
При этом, конечно, хотелось бы защитить сервис от CSRF. Ну и вообще, чтобы посторонние люди или боты не долбились по адресу сервиса без разрешения. Если бы запрос происходил через Form API, Друпал сделал бы всё за нас. Но и сами мы тоже можем, и на странице с формой для этого уже всё, что нужно — есть.
В Drupal 7 каждая форма защищена парой скрытых значений в $form['form_id']
и $form['form_token']
, соответственно, мы можем их подобрать и использовать при отправке на сервер. Для простоты, сделаем эти значения частью пути к сервису.
var form = $('#my-custom-form');
var form_id = form.find('input[name="form_id"]').val();
var form_token = form.find('input[name="form_token"]').val();
var url = '/my-custom-service/' + form_id + '/' + form_token;
$.getJSON(url, function (data) {
alert('Все готово!');
});
В hook_menu()
пункт, отвечающий за генерацию ответа, оформим так:
$items['my-custom-service/%/%'] = array(
'page callback' => '_my_custom_service',
'access callback' => '_my_custom_service_access',
'access arguments' => array(1, 2),
'type' => MENU_CALLBACK,
);
То есть мы передаем в access callback
эти два значения как аргументы. Тогда в функции, управляющей доступом, мы можем легко проверить валидность токена:
function _my_custom_service_access($form_id, $form_token) {
return drupal_valid_token($form_token, $form_id);
}
И всё.