×

Использование 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 ниже, чем у стандартного шаблона.

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

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

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

logo