В этой записи я расскажу о своём личном велосипеде с использованием 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 ниже, чем у стандартного шаблона.
Если кто-нибудь предложит более оптимальный вариант, я буду очень рад =)
Вот читал же, но забыл =) Так проще. Нужно будет убрать этот велосипед.
Ответить