Недавно делали сайт крупной городской сети магазинов фототоваров — куча товаров, различные типы продукции, несколько типов цен(ну и, естественно, связь с 1С). Поскольку товары имеют различные характеристики, решили их хранить в разных инфоблоках. При импорте продукции автоматически создаем папки, в них кладём index.php. Но index.php должен быть персонифицирован - указан свой идентификатор инфоблока, выбраны свойства для фильтра, свойства для детального просмотра и т.п., а кое-где должен быть и шаблон компонента другой[spoiler] Решена эта задача была в лоб - в модифицированный класс для импорта xml(модифицировался он изначально по куда более важным причинам) была вставлена болванка для индексной страницы, в которую вписывались данные:
Способ, конечно, не красивый, но рабочий. Мне он не особо понравился(делал сиё чудо, в хорошем смысле этого слова, другой разрабочтик) и в очередные выходные любопытство одержало верх над ленью и желанием поваляться на диване и посмотреть новые серии футурамы.
Полчасика поковырявшись в исходниках битрикса, я нашел много нового и интересного, в том числе функции для работы со страницей и настройками компонента.
Работа с компонентом строится на классе PHPParser(/bitrix/modules/main/classes/general/php_parser.php) - он содержит набор функций для парсинга пхп-кода, поиска компонентов и выдачи массива с данными конкретного компонента.
Для начала надо знать местоположения нужного компонента - имя файла и номер строки, в которой расположен компонент(вернее сказать так - номер строки, которая принадлежит коду вставки компонента). Это можно сделать двумя способами:
Самому найти номер строки в файле
Получить список компонтов на странице и найти нужный
Второй способ удобней, т.к. в данном случае не придется после редактирования страницы корректировать номер строки. Итак. Для работы со страницей необходимо сначала прочитать её код в строку:
START - позиция начала кода компонента(смещение относительно начала файла), END - позиция конца, DATA содержит сведенные в массив настройки компонента. По массиву DATA можно осуществлять поиск компонента, например, по его шаблону или настройками, в случае, если невозможна адресация по индексу - допустим, если существует вероятность в будущем добавления ещё одного компонента перед нашим.
Вот так можно получить номер строки по смещению относительно начала файла(строчка позаимствована из того же PHPParser):
Тут, думаю, всё должно быть понятно — порядок элементов в $arComponent['DATA'] соответствует функции IncludeComponent за искючением VARIABLE - имя переменной, которой присваивается результат подлкючения компонента(см. ниже генерацию кода компонента). Модифицируем параметры компонента в соответствии с поставленной задачей. У меня это выглядит примерно так:
// Устанавливаем свойства для фильтра
$arComponent['DATA']['PARAMS']['FILTER_PROPERTY_CODE'] = $propertiesFilter;
// Выводим все свойства
$arComponent['DATA']['PARAMS']['DETAIL_PROPERTY_CODE'] = $properties;
$arComponent['DATA']['PARAMS']['IBLOCK_ID'] = $iblockId;
// Устанавливаем путь для чпу
$arComponent['DATA']['PARAMS']['SEF_FOLDER'] = '/goods/' . $arIblock['CODE'] . '/';
// Прячем ярлык настройки
$arComponent['DATA']['FUNCTION_PARAMS'] = array('HIDE_ICONS' => 'Y');
Если необходимо в качестве значения указать переменную, делается это привычным для битрикса способом:
Параметры установили, теперь надо преобразовать массив в компонента. К сожалению, отдельной функции для преобразования, как я понял, нет - код, производящий генерацию, находится в файле /bitrix/modules/main/public/component_props2.php, оттуда он и был заимствован и слегка модифицирован:
В файле /bitrix/modules/main/admin_tools.php, в котором описана данная фукнция, имеется ещё несколько полезных функций, который могут пригодиться(например, установка свойств страницы - SetPrologProperty()). Модификация страницы-болванки закончена, сохраняем её в новый файл:
На выходе имеем полностью настроенный скрипт для конкретного инфоблока. Вот, в общем-то, и всё - несколько десятков строк кода и у нас есть правильный способ настройки/вставки компонентов. В заключение хочу рекомендовать к изучению скрипты из папки /bitrix/modules/main/public/ - отправная точка для всего, что только может понадобится при динамическом управлении страницей, разделом или компонентом.
Кусок кода без прерывания моими рассуждениями для удобства:
Ну и маленький бонус:-) (ибо в заголовок поста не вписывается) — за создание/редактирование меню отвечает функция CFileMan::SaveMenu(). Пример добавления нового пункта меню:
CModule::IncludeModule('fileman');
$menuPath = '/.top.menu.php';
// Получаем массив
$res = CFileMan::GetMenuArray($_SERVER['DOCUMENT_ROOT'] . $menuPath);
// Добавляем элемент
$res['aMenuLinks'][] = array('Тест', '/test/', array(), array(), '');
// Сохраняем, указывая имя сайта и путь к меню от корня сайта
CFileMan::SaveMenu(array('s1', '/.top.menu.php'), $res['aMenuLinks'], $res['sMenuTemplate']);
Я потрясен изобретательностью нашего народа и умением находить нестандартные решения! Уверен на 99,9%, что ваши задачи решаются всего лишь разработкой нескольких компонентов с нужной логикой. Или на крайний случай можно просто создавать файлы сразу с нужной структурой.
Мы тоже используем подобное решение при разработке магазинов. Допустим имеется 40 инфоблоков (товарные группы с различными наборами характеристик, которые используются при сравнении товаров, фильтрах и т.д.) Идеология и архитектура 1С-Битрикс такова, что после создания логической структуры -- типов инфоблоков и инфоблоков с разделами, потом, еще необходимо создать физическую структуру -- 40 папок различной вложенности, а там файлы index.php и section.php и возможно другие, например, включаемые области. В файлы первого типа нужно положить комплексный компонент и настроить его уникально для каждой товарной группы. В файлы второго типа автоматом вписать title, keywords, description.
Сейчас, мы создаем все дерево папок и файлов скриптом. Имена папок берутся из символьных кодов инфоблоков, а уровни вложенности определяются исходя из того инфоблок это или тип инфоблока. Затем настраиваем параметры компонентов вручную (хотя часть, например, имя объектов для постраничной навигации, тип инфоблока, инфоблок, ЧПУ и др. уже сейчас берутся из настроек инфоблоков). Я склоняюсь к тому чтобы и оставшиеся настройки компонента (какие свойства где выводить) хранить где-то в свойствах инфоблоков, чтобы уже в одном месте управлять всем каталогом товаров (все дерево папок и файлов при этом должно автоматически перегенерироваться). Например, в настройках свойства можно иметь чекбоксы для выбора места его отображения: список, детальная, фильтр, сортировка, сравнение.
Был у меня сайт, в котором под тысячу товарных групп нужно было создавать. И не знаю что бы было, если бы я стал пользоваться данным способом, а потом пришлось поменять какую-то маленькую мелочь
Задачей было сделать так, чтобы заказчик мог без проблем добавлять новые товарные группы и эти группы так же без проблем показывались на сайте, не прибегая к помощи разработчика. Наши методы(что не понравившийся мне, что здесь описанный) как нельзя лучше встроились в допиленный xml-импорт, поэтому искать другие пути, может быть и более красивого, но трудозатратного решения мы не стали
Всё зависит от конкретной мелочи и первоначальной продуманности схемы. Если для добавления текста перед компонентом требуется изменить 1000 файлов, то разработчику надо по рукам надавать:-) Хотя, на самом деле, за пять минут можно наваять скрипт, который модифицирует все файлы. Да и с тысячей товарных групп, мне кажется, надо уже много чего нового придумывать помимо организации отображения. Мы сейчас занимаемся разработкой проекта с 3000 разделов, 36000 товаров и 800000 цен. Тут не то, что стандартные компоненты, от которых мы отказались, затягивают время генерации страницы, тут даже некоторые запросы через апи выполняются по 3-5 секунд(но это уже отдельная тема для разговора)
Нет, персональная цена для каждого пользователя(пользователь имеет доступ только к определенным разделам).
Т.е. без ТЗ работаете, придумывать алгоритмы будите по хожу пьесы?
Да нет, ТЗ есть. Последнее процитированное Вами предложение не относится к мыслям о проекте(хотя да, некоторые места пришлось переделывать «по ходу пьесы»)
Ну, вы же знаете, что пути заказчика неисповедимы, поэтому изменения могут быть какими угодно и возникают тогда, когда уже все сделано. Например, "нам тут сеошники нашептали..." и понеслось.
А разрабатывать каталог для неопределенного (даже чисто теоретически) количества товарных групп через файловую структуру - "по моему дерьмометру это зашкаливает" (с) MIB. Один разбор километрового urlrewrite.php чего только стоит.
В общем, тяжело придумать задачу и условия, которые бы вынудили меня на использование такого подхода, тем более если просто необходимо менять параметры компонента.
Роман, вас какая-то конкретная проблема интересует или в общем? Если в общем, то разрабатываю компоненты и/или модули для таких проектов, все зависит от требований и задач.
Был у меня сайт, в котором под тысячу товарных групп нужно было создавать. И не знаю что бы было, если бы я стал пользоваться данным способом, а потом пришлось поменять какую-то маленькую мелочь
Какую идею придумали Вы? Общий подход имеется ввиду.
Конкретно для этого проекта был разработан модуль, через который выполняется все управление каталогом. По сути надстройка для инфоблоков. Автоматически создаются/редактируются/удаляются инфоблоки для товарных групп и прочая автоматизация для упрощения жизни администраторов. Получается, что визуально администратор работает с одним инфоблоком, через секции (товарные категории) управляет их свойствами, а что на самом деле создаются сотни вспомогательных инфоблоков его не касается. Служебные же инфоблоки скрываются из меню, т.к. список внушительных размеров полуался. Кстати, для реализации этого просил добавить событие OnBuildGlobalMenu, к моему большому удивлению и радости пожелание приняли и оперативно добавили (хотя, наверное не только я один просил). И, разумеется, писались свои компоненты.
А если бы задача не стояла управления каталогом через админку (а только через 1С, к примеру), то решается все куда проще, одними компонентами, причем сложность этих компонентов не так и высока.
Для задачи, которую привел Андрей, можно просто сделать компонент-обертку, который бы выбирал фильтруемые свойства инфоблока и со списком этих свойств подключал стандартный компонент. А кастомизация используемого стандартного комопнента позволила бы избавиться и от этой обертки, все делать в одном. Если я правильно понял решаемую проблему, конечно.
Но мелких заморочек много все равно, конечно. Нужных интерфейсов в инфоблоках для полного счастья при реализации таких задач практически нет.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».