Использование AJAX и JSON в компонентах битрикса

В этой записи я расскажу о своём личном велосипеде с использованием AJAX и JSON при написании компонентов к Bitrix.

Проблема первая – куда отправлять запрос?

Логичным решением будет создать внутри директории компонента папку для хранения всех скриптов, к которым компонент будет обращаться посредством ajax. Допустим, она будет называться ajax. Но как указать в скрипте путь к этим файлам?

Проблема заключается в том, что при подключении компонента на какую-либо страницу, текущим каталогом с точки зрения JavaScript будет каталог той страницы, на которую был подключен компонент. Можно попытаться задать в скрипте путь к странице в виде

$.post('ajax/foo.php',formData,viewResult);

Скрипт обратится по адресу http://адрес.сайта/«каталог страницы, на которую подключен коспонент»/ajax/foo.php и ничего там не найдёт, а если и найдёт, то не то что должен, т.к. нужный нам файл лежит не в директории со страницей с которой вызван компонент, а в папке компонента.

Решение проблемы

Если компонент гарантированно не будет перемещаться или переименовываться, то в скрипте можно задать полный путь от корневой директории сайта.

$.post('/bitrix/components/пространство имён/название компонента/ajax/foo.php',formData,viewResult);

Это лишает наш компонент универсальности и переносимости, т.к. пространство имён на другом сайте может отличаться. Поэтому я для себя придумал вот такой велосипед.

Получение информации о директории, в которой находится подключаемый компонент

Я долго искал переменную (или константу), из которой было бы выудить информацию о директории, в которой находится компонент. В итоге лучшим решением оказалось распарсить константу __FILE__ и предать её в скрытое поле формы. Делается это следующим образом.

Путь к директории определяется в коде компонента и записывается в массив $arResult

//проверяем чем разделён путь и разделяем его на директории
if(strpos(__FILE__,"/") !== false){
  $arrThisDir = explode("/",__FILE__);
}else{
  $arrThisDir = explode("\\",__FILE__);
}

//ищем в массиве ключ папки битрикс
$firstDirKey = array_search('bitrix', $arrThisDir);

//переменная, в которую будем записывать путь
$arResult["COMPONENT_DIRECTORY"] = "/";

//записываем путь к директории
for($key = $firstDirKey; $key < count($arrThisDir) - 1; $key++){
  $arResult["COMPONENT_DIRECTORY"] .= $arrThisDir[$key]."/";
}

Запишем его в скрытое поле формы

<input type="hidden" id="COMPONENT_DIRECTORY" value="<?=$arResult["COMPONENT_DIRECTORY"]?>" />

Теперь скрипт гарантированно будет обращаться к нужному файлу

//получем директорию из скрытого поля
var compDir = $("#COMPONENT_DIRECTORY").val();
  
//отправляем запрос
$.post(compDir + 'ajax/foo.php',formData,viewResult);

Проблема вторая – доступ к классам Bitrix

Если просто создать файл в папке компонента и обратиться к нему, то ничего хорошего не получится, т.к. из этого скрипта не будет доступа к API Битрикса.

Решение проблемы

Чтобы получить доступ к API, нужно подключить пролог.

require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");

Казалось бы, всё хорошо, и всё работает, но…

Проблема третья – использование JSON

При подключении пролога к странице, применяется стандартный шаблон сайта. Мало того, что вся эта информация в данном скрипте не нужна, так она еще и не позволяет пользоваться JSON.

Решение проблемы

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

Возникает вопрос, на каких условиях его подключать? Писать отдельное правило для каждого компонента использующего AJAX не совсем хорошо. Логичнее использовать префикс в имени файла и подключать шаблон по нему.

Я выбрал префикс «–ajax» и создал вот такое условие для подключения шаблона.

strpos($_SERVER["PHP_SELF"], 'ajax')!==false

Задаётся это всё в меню – «Настройки продукта» — «Сайты» — «Список сайтов». Главное – не забыть поставить сортировку шаблона для AJAX ниже, чем у стандартного шаблона.

Условие для подключения пустого шаблона

Условие для подключения пустого шаблона

Если кто-нибудь предложит более оптимальный вариант, я буду очень рад =)

9 комментариев

nook
nook

require ($_SERVER[«DOCUMENT_ROOT»] . «/bitrix/modules/main/include/prolog_before.php»);
require ($_SERVER[«DOCUMENT_ROOT»] . «/bitrix/modules/main/include/epilog_after.php»);

Ответить

Морозов Максим

Спасибо, завтра поправлю у себя =)

Ответить

Виктор

В коде component.php получить URL текущей папки можно через $this->GetPath(), так что для определения пути вполне достаточно
$arResult[«COMPONENT_DIRECTORY»] = $this->GetPath();

Ответить

Морозов Максим

Спасибо =) Завтра на работе попробую. А в статье тогда, попозже напишу что так делать нельзя *CRAZY*

Ответить

murzix

Так действительно удобнее =)

Но разделитель всё равно нужно получать, т.к. сервер может быть и на винде.

Ответить

Виктор

Не совсем понял, о каком разделителе идет речь.
Если вы про разделитель в пути к файлу, то он хранится в предопределенной константе
DIRECTORY_SEPARATOR.

Ответить

Морозов Максим

Блин. Как-то я невнимательно мануалы читаю. *CRAZY* Спасибо =)

Ответить

Ваш отзыв

logo