Как найти где располагается класс в битриксе?
По долгу службы вынужден разбираться в битриксе, при этом не имея доступа к исходному коду (приходится просматривать код через админку битрикса).
Встретился совершенно непонятную мне строчку. Хотел разобраться что возвращают методы, но не понимаю, как найти где они располагаются.
Строчка выгляди так:
if(project_title::getUserRule($USER_DATA["GROUPS"])
Как найти класс project_title?
- Вопрос задан более трёх лет назад
- 3032 просмотра
1 комментарий
Оценить 1 комментарий
Куда добавлять свои классы в Bitrix?
Здравствуйте! Возникла необходимость реализовать дополнительный функционал для битрикса, а именно Assets как в Yii2, то есть я хочу реализовать декоратор над стандартным Assets у битрикса. Сразу возник вопрос, куда помещать файл с классом, в какие namespaces и папки, без привязки к конкретному проекту или компоненту? Заранее спасибо
P.S: Если в битриксе уже что-то такое есть, то поделитесь инфой, пожалуйста
- Вопрос задан более двух лет назад
- 373 просмотра
Комментировать
Решения вопроса 1
PHP, Golang, React
Есть несколько способов, главное помнить что классы не ради классов, а для поддерживаемого кода и его повторного использования.
1. Автозагрузка классов с помощью Composer (многие используют).
2. Написать свою автозагрузку. (если у вас что то сильно не стандартное)
3. В виде модуля bitrix, автозагрузка будет (имхо самый правильный вариант для битрикса)
При использовании composer, файлы классов могут лежать, где угодно, но хорошей практикой считается хранить их (как и папку vendor) на уровень выше публичной папки.
В Namespace вы не ограничены, главное делайте явную и четкую структуру и названия несущие смысловую нагрузку.
ЗЫ: Не забываем про DRY, KISS, SOLID и т.д.
Организация кода в Битрикс — к обсуждению

Не сохранилась половина статьи про исключения ….(( а написал много. Поэтому пока их отложу, а напишу про битрикс.
Несмотря на весь тот свод правил, которые предлагает нам битрикс, можно организовывать хранение своего кода по разному. В статье я постараюсь предложить варианты, который хотел бы видеть в проектах, с которыми работаю. Он не идеален, он не панацея, доступен для обсуждения, я всегда открыт для ваших предложений.
Что нам предлагает битрикс
Слава разработчикам, что они наконец-то начали отделять код ядра от кода разработчиков. С 12й версии битрикс появилась возможность использовать директорию /local (более полная поддержка пришла с 14й версией). Данная директория должна находиться в корне сайта. По структуре она полностью повторяет структуру директории /bitrix, за тем исключением, что в ней нет файлов ядра (встроенных модулей, компонентов и т.д.). Что же может содержать в себе директория /local? Основываясь на статье перечисляю поддерживаемые вложенные директории:
- /local/activities — действия из модуля бизнес-процессов
- /local/components — сторонние компоненты
- /local/gadgets — гаджеты для рабочего стола админки
- /local/modules — сторонние модули
- /local/php_interface — работает только init.php и директория user_lang (для подмены языковых файлов)
- /loca/templates — шаблоны сайта
Директория local имеет приоритет перед /bitrix, т.ч. при одинаковых именах файлов будет использован вариант из /local.
Шаблон сайта
Вроде все базово, все и всё знают, однако сколько проектов ни видел, нигде нет единого варианта. Шаблон сайта должен находиться в директории /local/templates/. Структура файлов директории с шаблоном сайта достаточно подробно расписана тут, а я все-таки остановлюсь немного подробнее на нескольких файлах:
-
header.php и footer.php. Пожалуйста — не стоит размещать в них логику. Только в самых крайних случаях. Надо понимать — что это файлы шаблонов — а в шаблонах должны быть только шаблоны, и ничего более. Тупой пример с одного из проектов, где в header.php определяется тип пользователя. Мало того, что логика в шаблоне, так и код еще ужасный:
//ТАК ДЕЛАТЬ НЕЛЬЗЯ В ПРИНЦИПЕ!
$GLOBALS [ «OPT_USER» ] = false ;
if ( $USER -> IsAuthorized ( ) ) <
$uGroups = $USER -> GetUserGroupArray ( ) ;
if ( in_array ( 11 , $uGroups ) )
$GLOBALS [ «OPT_USER» ] = true ;
Компоненты, свой — чужой
Часто наблюдаю нелепую ситуацию. Разработчик написал компонент, узкоспециальный, который решает конкретную в рамках продукта задачу. Сохраняет код компонента в /local/component/mx/my.component. А шаблон внезапно выносит зачем-то в шаблон сайта, или того хуже — в /bitrix/templates/.default/components/mx/my.component/templates/. Есть еще уникумы, которые в шаблоне своего компонента пишут result_modifier.php, который изменяет результат собственной выборки. На мой взгляд это полный бред. Если уж ты написал компонент, который правильно будет работать с конкретным шаблоном, то храни шаблон компонента внутри директории компонента /local/components/mx/my.component/templates. Если шаблон этого компонента работает исключительно с определенным шаблоном сайта, то я бы назвал шаблон этого компонента по имени шаблона сайта. И уж тем более не нужно использовать result_modifier.php, когда эту логику можно оставить в теле компонента.
Также, разработчики часто забывают про возможности ООП внутри компонентов. Если кто не знает, то уже давно внутри компонента можно создать файл class.php, который должен содержать класс, унаследованный от CBitrixComponent.
Благодаря этому можно использовать наследование классов других компонентов при создании своих — иногда это очень полезный инструмент. Подробнее — тут.
Перед тем, как кастомизировать встроенный компонент — нужно 1000 раз подумать, а действительно ли он не соответствует вашим требованиям? Может вместо копирования встроенного компонента лучше прибегнуть к написанию собственного? Если вы все-таки решили скопировать встроенный компонент, то обязательно документируйте, что и где вы изменили внутри этого компонента, это сильно поможет другим разработчикам, а также поможет при обновлении компонентов при обновлении ядра.
Собственные и сторонние классы, библиотеки
Я предлагаю для хранения библиотек и классов завести директорию /local/lib. Для php библиотек — /local/lib/backend, для js — /local/lib/frontend
Внутри директории для php библиотек можно хранить библиотеки и классы по типу, описанному в одной из моих статей. В идеале — приводить свои библиотеки к виду, регламентируемому замечательным composer (про него когда-нибудь тоже напишу).
Каждая js библиотека должна храниться в отдельной директории, т.к. для библиотеки часто в комплекте может идти несколько css файлов, map, или еще чего. Ну и удобнее так будет, ибо нужно хранить и исходник файла, и его минифицированную версию.
Для конфигураций предлагаю создать директорию /local/config, внутри которой вижу следующие файлы:
- const.php — константы вашего проекта
- events.php — вызовы AddEventHandler для всех возможных кастомных обработчиков событий проекта.
- frontend.php — регистрация js библиотек из /local/lib/frontend/ — об этом ниже
Не нужно подключать все свои js файлы прямым включением в шапку сайта. Для подключения js файлов в битриксе есть добротный класс CJSCore. Можно зарегистрировать все свои js библиотеки, и подключать их строго на нужных страницах. Для регистрации библиотек используем файл, который должен быть подключен на всех страницах нашего проекта — /local/config/frontend.php
Ниже в примере показано, как зарегистрировать библиотеку и подключить ее:
Содержимое файла /local/config/frontend.php
Собственный тип пользовательских полей в 1С Битрикс
Для решения некоторых задач порой не хватает стандартного набора пользовательских полей поставляемых из «коробки» 1С Битрикс Управление сайтом. Однако вы можете создать свой собственный тип пользовательского поля, определить его внешний вид и даже подключить какие-нибудь сторонние jQuery плагины. В данной статье мы рассмотрим несколько таких полей:
- Привязка к пользователю
- Выбор цвета
Первый можно использовать для фиксации автора изменения записи в HL блоке, второй для изменения внешнего вида элемента на странице. И так приступим.
Находим подходящий стандартный тип поля
Естественно мы не будем писать всё с нуля и изобретать велосипеды, а подберём подходящий под наши задачи существующий класс реализующий нужный тип поля. Все классы пользовательских полей хранятся в главном модуле в папке /bitrix/modules/main/classes/general/ файлы классов имеют префикс usertype, здесь вы найдёте следующий набор классов:
- usertypebool.php
- usertypedate.php
- usertypedbl.php
- usertypeelement.php
- usertypeenum.php
- usertypefile.php
- usertypeint.php
- usertypesection.php
- usertypestr.php
- usertypestrfmt.php
- usertypetime.php
- usertypeurl.php
В принципе USER_ID можно реализовать на основе usertypeint, но давайте дадим администратору возможность удобного выбора пользователя, к тому же возможно нам потребуется сделать это поле множественным.
Подготовка init.php и пространства имён
Давайте для начала подготовим место где будем хранить все наши пользовательские классы, константы и обработчики событий. Я предпочитаю использовать папку local с вот такой структурой:
первый делом рассмотрим init.php
IsAdmin())< echo ''.(!empty($name) ? $name.': ' : ''); if($mode) < var_dump($val); >else < print_r($val); >echo ''; if($die) die; > >
Здесь помимо подключения констант, автозагрузки классов и обработчиков событий определена одна вспомогательная функция print_p() при помощи которой можно удобно просматривать содержимое переменных.
Рассмотрим остальные файлы.
Файл constants.php
В константах я определил пару путей для удобства дальнейшего обращения к лежащим в них файлам.
Файл autoload.php
APP_CLASS_FOLDER . 'UserType/CUserTypeUserId.php', 'lib\UserType\CUserTypeColor' => APP_CLASS_FOLDER . 'UserType/CUserTypeColor.php' ]);А здесь вызовем загрузчик классов битрикс и добавим в него массив с нашими будущими классами (ссылка на документацию).
Файл event_handler.php
addEventHandler('main', 'OnUserTypeBuildList', ['lib\UserType\CUserTypeUserId', 'GetUserTypeDescription']); $eventManager->addEventHandler('main', 'OnUserTypeBuildList', ['lib\UserType\CUserTypeColor', 'GetUserTypeDescription']);Чтобы наши кастомные свойства были доступны в списке выбора типа пользовательского поля, нам необходимо перехватить событие создания этого списка и дополнить его своими типами свойств, вызвав зарезервированный метод GetUserTypeDEscription.
Создаём класс для определения своего пользовательского свойства
Как вы уже поняли и листинга файла с константами, наши классы будут лежать в директории /local/php_interface/lib/. Я предпочитаю разделять собственные классы на группы по директориям, например классы для работы с инфоблоками храню в папке Iblock, работы с каталогом в Catalog, для пользовательских свойств предлагаю создать папку UserType.
И так в директории /local/php_interface/lib/UserType/ создадим 2 файла CUserTypeUserId.php и CUserTypeColor.php. Начнём со свойства «Привязка к пользователю». Определим пространство имён, подключим доп.классы ядра.
'N' // S - строка, N - число и т.д. "USER_TYPE" => 'userid', //Уникальный идентификатор типа свойств "CLASS_NAME" => __CLASS__, "DESCRIPTION" => 'Привязка к пользователю', "BASE_TYPE" => \CUserTypeManager::BASE_TYPE_INT, ); > /** * Обязательный метод для определения типа поля таблицы в БД при создании свойства * @param $arUserField * @return string */ function GetDBColumnType($arUserField) < global $DB; switch(strtolower($DB->type)) < case "mysql": return "int(18)"; case "oracle": return "number(18)"; case "mssql": return "int"; >return "int"; > >В принципе, этого достаточно чтобы наш новый тип свойств появился в этом списке:
- GetList() — Получаем список значений
- GetEditFormHTML() — Получить HTML формы для редактирования свойства
- GetEditFormHTMLMulty() — Получить HTML формы для редактирования МНОЖЕСТВЕННОГО свойства
- GetAdminListViewHTML() — Получаем HTML для списка элементов в админке
- getEmptyCaption() — Получаем текст для пустого значения свойства
- GetAdminListEditHTML() — Получить HTML для редактирования свойства в списке админ-панели
- GetAdminListEditHTMLMulty() — Получить HTML для редактирования МНОЖЕСТВЕННОГО свойства в списке админ-панели
- GetFilterHTML() — Получаем HTML блок для фильтрации списка элементов по этому свойству
Я не стану размещать здесь все методы, хочу отметить лишь GetList(), т.к. в стандартных классах он обычно возвращает объект CDBResult, а мне больше нравится подготовить данные для отображения заранее, поэтому в нём я получаю массив значений для отрисовки его в методах GetEditFormHTML() и подобных:
/** * Получаем список значений * @param $arUserField * @return array|bool|\CDBResult */ public function GetList($arUserField) < $rsEnum = []; //GROUPS_ID - Администраторы, контент редакторы $dbResultList = \CUser::GetList(($by='id'), ($order='asc'), ['GROUPS_ID'=>[1, 5]]); while ($arResult = $dbResultList->Fetch()) < $rsEnum[] = [ 'ID' =>$arResult['ID'], //Формат отображения значений 'VALUE' => $arResult['NAME'] . ' ' . $arResult['LAST_NAME'] . ' (' . $arResult['EMAIL'] . ')' ]; > return $rsEnum; >
Оба класса целиком вы найдёте в конце статьи. Подключив полноценный класс мы получаем вот такое свойство:

За вывод этого списка отвечает метод GetEditFormHTML(). В настройках свойства так же можно включить множественный вариант его работы, который выглядит так:

В данном случае работает метод GetEditFormHTMLMulty(). Если у класса корректно определены метод
- GetAdminListViewHTML()
- GetAdminListEditHTML()
- GetAdminListEditHTMLMulty()
Значение свойств будут так же корректно отображаться и редактироваться в списке элементов:

На скриншоте виден так же блок фильтрации, он определяется методом GetFilterHTML() . Чтобы вывести собственное свойство в фильтр его можно добавить в настройках формы фильтра так:

Это свойство можно применять для того, чтобы связать запись HL блока с пользователем создавшим её или внёсшим в неё изменения, ставить ответственного за обработку записи (например если хранить в HL блоке какие-то не стандартные заявки от посетителей) и многое другое.
Пользовательское свойство «Цвет»
Давайте разберёмся с более экзотическим классов «Цвет». Иногда нужно дать возможность контент-менеджеру определять цветовую схему элемента (новости, статьи или какой-то части её оформления), обычно для этого создаётся простое свойство типа «строка» куда записывается цвет скопированный из Photoship или ColorPicker, однако это требует больше действий от контентщика. Давайте реализуем такой функционал прямо внутри элемента.
За основу возьмём стандартный класс типа пользовательского поля «Строка» и определим для него необычный внешний вид (метод GetEditFormHTML()) . Нам так же потребуется какой-нибудь jQuery плагин для выбора цвета, я остановил свой выбор на jQuery ColorPicker он обладает нужным функционалом имеет необходимые события и довольно прост в настройке.
И так, для начала скачаем этот плагин и загрузим всё в /local/media/ как помните выше я определил константу APP_MEDIA_FOLDER.
Создаём класс для свойства «Цвет»
Как и для первого класса нам нужно определить метод GetUserTypeDescription который будет вызван в момент построения списка доступных пользовательских свойств.
-
*
- USER_TYPE_ID — уникальный идентификатор *
- CLASS_NAME — имя класса методы которого формируют поведение типа *
- DESCRIPTION — описание для показа в интерфейсе (выпадающий список и т.п.) *
- BASE_TYPE — базовый тип на котором будут основаны операции фильтра (int, double, string, date, datetime) *
Самый примечательный метод здесь это GetEditHTML()
/** * Эта функция вызывается при выводе формы редактирования значения свойства. * * Возвращает html для встраивания в ячейку таблицы. * в форму редактирования сущности (на вкладке "Доп. свойства")
* Элементы $arHtmlControl приведены к html безопасному виду.
* @param array $arUserField Массив описывающий поле. * @param array $arHtmlControl Массив управления из формы. Содержит элементы NAME и VALUE. * @return string HTML для вывода. * @static */ function GetEditFormHTML($arUserField, $arHtmlControl) < if(!$arUserField['VALUE'])< $arHtmlControl['VALUE'] = htmlspecialcharsbx($arUserField["SETTINGS"]["DEFAULT_VALUE"]); >else < $arHtmlControl['VALUE'] = $arUserField['VALUE']; >//CSS файлвы не захотели подключаться через Asset::getInstance()->addCss() поэтому подтягиваем // их через HTML загружаемый на странице редактирования свойства $return = ' '; \CJSCore::Init(['jquery2']); Asset::getInstance()->addJs(APP_MEDIA_FOLDER . 'js/colorpicker.js'); Asset::getInstance()->addJs(APP_MEDIA_FOLDER . 'js/CUserTypeColor.js'); $return = $return . ' '; return $return; >
В нём я подключаю css и js файлы плагина и пользовательский CUserTypeColor.js в котором осуществляется запуск плагина и указаны его настройки. Здесь блок colorpickerHolder предназначен для отрисовки формы выбора цвета а в поле colorpickerHolderInput записывается значение света, когда пользователь меняет параметры в форме или выбирает цвет на палитре при помощи мышки. Т.к. это демонстрационный пример, методы типа GetAdminListViewHTML() унаследованы у пользовательского типа «Строка» и просто выводят значение цвета в виде HEX-кода.
В результате подключения такого класса и создания пользовательского свойства типа «Цвет» получаем вот такой вот функционал:
Его можно использовать для подсветки важных элементов в списке или другого визуального оформления страницы. Как и обещал все материалы из статьи прикреплю в виде архива.

