Интересные задачи верстки и клиентского программирования

Правильный старт и развитие bitrix проекта

добавил Шубин Александр 25 Июль, 2016


Считаем, что принято решение делать сайт на CMS и в качестве CMS был выбран битрикс. Дизайнер отрисовал картинку, верстальщик сделал html+css+js код и дальше начинает работу серверный программист. С чего начать проект? Как лучше организовать код? Об этом я хочу поговорить в данной статье. Здесь я не ставлю задачу объяснить каждую деталь подробно, не ставлю задачу показать прямо конкретные шаги, вроде выполните первое, выполните второе и т.д. Здесь я постараюсь обрисовать общую картину. Я хочу показать как должен быть устроен проект на битриксе с моей точки зрения. Если у вас есть какие то замечания, дополнения или уточнения, то пишите в комментарии. Было бы любопытно сравнить разные подходы к формированию структуры проекта.


Создание проекта

Начну с банальностей. Любой проект начинается с папки, так что создайте папку в любом удобном для вас месте. Эта папка будет корнем сайта, то есть если вы редактируете файл index.php в этой новой папке, то это все равно что вы редактируете файл /index.php на сайте (после синхронизации естественно). Ну это я думаю и так понятно. Если вы пользуетесь IDE, то можете создать новый проект через меню редактора, но суть та же останется — будет создана новая папка.

Контроль версий

Далее, сразу после создания папки, пока папка пуста делайте из этой папки репозиторий для системы контроля версий. Зачем нужен контроль версий и что это такое вы можете прочитать тут. Я пользуюсь гитом (git), так что для старта репозитория просто выполняю git init в нужной папке. Вы можете создать репозиторий любым удобным для вас способом. Например можно поставить «tortoseGit» под винду, это визуальный интерфейс, он добавляет новые пункты в контекстное меню по правой кнопке мыши в папке. Мне он кажется довольно простым и удобным, просто кликая мышкой без консоли можно управлять репозиторием.

После создания репозитория добавьте в корень папки файл .gitignore, где сразу пропишите папку /bitrix/ и все остальные папки которые вы точно не будете трогать. Полную копию битрикса я предпочитаю не хранить локально, однако же иногда бывает полезно выкачать что-то из папки bitrix и посмотреть детально как оно там устроено. И вот эти временные файлы после прописывания папки /bitrix/ в .gitignore точно не попадут в коммит.

В дальнейшем, когда уже начнете писать код, стоит сосредоточиться на какой то одной задаче, выполнить ее и сделать коммит с комментарием о выполненной задаче. Не нужно делать коммит по итогу суток, недели или хуже того стартовый коммит, и коммит с уже завершенным проектом. В этом случае вся суть контроля версий теряется. Да, иногда я и сам забываю сконцентрироваться на задаче, особенно когда их много, но в этом случае стоит добить текущую задачу и сделать общий коммит где расписать каждую из выполненных задач. Например, «сделан глобальный шаблон», «левое меню», «список разделов каталога», «раздел новостей» и т.д.

Есть множество всяких красивых схем ветвления, отдельная ветка под разработку, рабочая ветка, ветки по фичам, тэги версий и т.д. Все это безусловно круто, но если вы не понимаете зачем это все нужно, то просто отправляйте все в одну ветку master последовательно и не заморачивайтесь с ветками вообще. Все эти схемы ветвления предназначены во первых для группы разработчиков, и во вторых для запущенного или близкого к релизу проекта. Если вы понимаете зачем нужны ветки и как ими пользоваться то этот раздел статьи вам не очень то и нужен 🙂

Автодополнение

В битриксе довольно много всякого функционала и соответственно много всяких API функций. Вызов API можно конечно делать и вручную, прямо писать каждый раз название функции, либо открывать документацию и копировать, но гораздо удобнее настроить автодополнение в IDE. Лично я пользуюсь phpstorm от jetbrains, поэтому покажу настройку автодополнения именно тут. Для настройки автодополнения нам понадобится папка /bitrix/modules/ в исходных кодах, то есть ставите где-то битрикс, активируете его, обновляете до последней доступной версии и скачиваете из поставленного битрикса папку /bitrix/modules/. Битрикс не обязательно должен быть активированным, от шифрования кода они уже давно отказались, так что я думаю пойдет /bitrix/modules/ даже от пробной версии, но честно говоря не проверял.

После того как скачаете папку /bitrix/modules/, откройте phpstorm. У вас будет примерно такая картинка перед глазами

Окно нового проекта

Сделайте двойной щелчок мыши слева по строке «External Libraries». Откроется окошко добавления внешней библиотеки. Нажмите в этом окошке плюсик и укажите путь до скачанной папки /bitrix/modules/. После индексации папки, везде во всех файлах будет работать автодополнение по основным функциям. Будет работать переход по ctrl+клик на название функции, можно быстро посмотреть что именно происходит внутри конкретных функций ядра.

Папку /bitrix/modules/ можно использовать одну и ту же для многих проектов. В битриксе изменения происходят довольно часто, но все же прям кардинально они очень редко что меняют. Названия классов и функций, аргументы функций и т.д. как правило остаются без изменений очень долгое время. Так что папку /bitrix/modules/ вполне достаточно обновлять раз в полгода по выходу мажорных версий.

Верстка

Верстальщик как правило присылает результат в виде папки с html файлами и дополнительными подпапками типа /css/, /images/, /fonts/, /js/ и т.д. То есть собственно страницы сайта которые уже можно открывать в браузере и всякие стили и скрипты для этих страниц. Сразу же закиньте все присланное верстальщиком в корень проекта. Если в верстке используется gulp, grunt, sass, postcss и т.д. и вы верстку не планируете трогать, то достаточно закинуть скомпилированный проект, если планируете править верстку с использованием сборщиков проекта, то вы я думаю и так знаете что делать. Итого без сборщика проекта в корне у вас будет лежать папка /project_name или /verstka/ или еще что в которой лежат html файлы + все что в этих файлах используется. Это очень удобно, можно будет сразу присылать заказчику ссылку на верстку и ссылку на интегрированную в битрикс страницу, типа было и стало, ну либо самому сравнивать если вы собственный проект разрабатываете. Кроме того можно будет сразу брать нужные html куски из верстки не закрывая и не переключаясь из IDE. В дальнейшем, по завершении интеграции эту папку естественно стоит удалить.

Прямо сразу после добавления папки с версткой сделайте стартовый коммит в репозиторий. В дальнейшем если верстальщик работает отдельно от вас, делает только верстку и битрикс совсем не знает (то есть в готовом шаблоне битрикса он ничего не сможет поправить) вы просто копируете новые правки от верстальщика с перезаписью файлов в эту же папку с версткой. И сразу будет виден список изменений, которые он сделал. Система контроля версий просто подсветит все правки, которые вы уже распихаете по нужным местам шаблона сайта и шаблонов компонентов.

О папке local

Вообще вся работа будет вестись в папке local. По большей части это «/local/templates», «/local/php_interface/», «/local/modules/» и «/local/components/». Да, иногда требуется править и страницы публичной части, то есть например /index.php, или /about/index.php, но там практически всегда будут только вызовы компонентов, бывают и особо сложные разделы где много чего прямо на публичных страницах приходится делать, но не часто.

Преимущество папки local в том, что вы точно знаете, что любой код который там лежит был написан именно под этот проект. В папке /bitrix/ сильно дофига служебных и просто не нужных файлов, всякие старые или демонстрационные шаблоны, dbconn.php который отвлекает от init.php и т.д.. В общем чтобы найти что-то в папке /bitrix/ придется приложить больше усилий, потратить больше внимания на каждую операцию. В системе контроля версий не нужно писать огромный .gitignore с перечислением всех служебных папок (попробуйте например добавить в контроль версий только /bitrix/php_interface/init.php и проигнорировать dbconn.php из этой же папки), мы просто весь /bitrix/ игнорируем, а весь /local/ храним в репозитории. Проще говоря папка local гораздо удобнее.

То есть для нового проекта обязательно создаем папку /local/. В ней вам гарантированно потребуется папка templates с шаблоном сайта.

Шаблон сайта

Для начала создайте папку с шаблоном /local/templates/template_name/, либо /local/templates/.default/ если она вам больше нравится. Далее смотрите папку с версткой и копируете оттуда вообще все за исключением html кода в папку с шаблоном. То есть из верстки нужно взять все стили, все скрипты, все картинки, все шрифты и т.д. и положить их в папку с шаблоном. Причем все относительные пути надо сохранять. То есть копируем с сохранением структуры. Если верстальщик грамотный, то ни одного абсолютного пути он не напишет, все картинки будут браться из папки «../images/», а не «/images/», то есть из рядом лежащей папки, вне зависимости от того на какой глубине они лежат.

Весь глобальный шаблон сайта на битриксе это по сути два файла header.php и footer.php в папке с шаблоном. Что должно быть в файле header.php на мой взгляд? Вот примерно такое

<?if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
/**
 * @global CMain $APPLICATION
 * @global CUser $USER
 */
$dir = $APPLICATION->GetCurDir();
$page = $APPLICATION->GetCurPage();
$show_left_sidebar = $APPLICATION->GetDirProperty("show_left_sidebar");
$assets = \Bitrix\Main\Page\Asset::getInstance();
?><!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <?

    /**
     * CSS
     */
    $assets->addCss(SITE_TEMPLATE_PATH . '/css/reset.css');
    $assets->addCss(SITE_TEMPLATE_PATH . '/css/owl.carousel.css');
    $assets->addCss(SITE_TEMPLATE_PATH . '/css/owl.theme.css');
    $assets->addCss(SITE_TEMPLATE_PATH . '/css/owl.transitions.css');
    $assets->addCss(SITE_TEMPLATE_PATH . '/css/animate.min.css');
    $assets->addCss(SITE_TEMPLATE_PATH . '/css/jquery.formstyler.css');
    $assets->addCss(SITE_TEMPLATE_PATH . '/css/fancybox/jquery.fancybox.css');
    $assets->addCss(SITE_TEMPLATE_PATH . '/css/main.css');

    /**
     * JS
     */
    //VENDOR
    \CJSCore::Init(array('jquery'));
    $assets->addJs(SITE_TEMPLATE_PATH . '/vendor/owl.carousel.min.js');
    $assets->addJs(SITE_TEMPLATE_PATH . '/vendor/jquery.maskedinput.min.js');
    $assets->addJs(SITE_TEMPLATE_PATH . '/vendor/jquery.fancybox.pack.js');

    //LOCAL
    $assets->addJs(SITE_TEMPLATE_PATH . '/js/helpers.js');
    $assets->addJs(SITE_TEMPLATE_PATH . '/js/main.js');
    $assets->addJs(SITE_TEMPLATE_PATH . '/js/order.js');
    $assets->addJs(SITE_TEMPLATE_PATH . '/js/ajax.js');
    $assets->addJs(SITE_TEMPLATE_PATH . '/js/catalog.js');
    $assets->addJs(SITE_TEMPLATE_PATH . '/js/blog.js');


    /**
     * BITRIX ->ShowHead()
     */
    $APPLICATION->ShowMeta("robots", false);
    $APPLICATION->ShowMeta("keywords", false);
    $APPLICATION->ShowMeta("description", false);
    $APPLICATION->ShowLink("canonical", null);
    $APPLICATION->ShowCSS(true);
    $APPLICATION->ShowHeadStrings();
    $APPLICATION->ShowHeadScripts();
    ?>
    <title><? $APPLICATION->ShowTitle() ?></title>
</head>

Практически на всех сайтах, которые меня просят доработать, в шаблоне я вижу либо старые варианты подключения скриптов и стилей $APPLICATION->AddHeadScript(‘src’), либо же вообще оставшееся от верстки подключение тэгами <link> и <script>. Между тем уже давно в битриксе есть штатное удобное подключение, получаем экземпляр класса \Bitrix\Main\Page\Asset и дальше функциями addJs() и addCss() подключаем скрипты и стили. Если скрипты и стили подключены в шаблоне сайта, то они объединятся в один файл template_random.css и template_random.js (если это включено в настройках конечно же). Если скрипты и стили тем же классом Asset подключаются в любом другом месте, то они будут добавлены в отдельный файл page_random.css и page_random.js. То есть общие для всех страниц файлы кешируются отдельно от скриптов и стилей нужных для конкретной страницы.

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

Пользоваться файлами style.css и script.js в папке с шаблоном компонента вообще не стоит. Да в целом это может быть удобно когда подключаешь компонент на странице, и автоматом подтягиваются все его стили, ни о чем больше думать не нужно. Однако для правок лазить по папкам всех шаблонов и искать эти кусочные стили дикий геморрой. Поэтому все стили для сайта должны лежать в папке с шаблоном, в подпапке /css/ например. Точно так же и со скриптами, все скрипты должны быть в папке /js/ шаблона. Название у папки может быть любое, главное чтобы не в корне сайта и не в папках с шаблонами компонентов.

Скрипты стоит подключать именно в файле header.php и именно функцией addJs(), даже если в верстке скрипты по модному вынесены в конец страницы. В битриксе, в настройках есть галочка которая переносит все скрипты в конец страницы, вне зависимости от того где они были подключены. Поэтому как то специально извращаться со скриптами не нужно. Гораздо удобнее помнить что вообще все внешние файлы, и css и js подключаются в файле header.php в тэге head.

Сторонние плагины и библиотеки желательно подключать отдельно, чтобы сразу было видно где скрипты написанные специально для этого сайта, а где скрипты которые не нужно трогать. Идеально если верстальщик все внешние скрипты и стили положил в отдельную папку /vendor/. В вышеприведенном коде все внешние скрипты подключены в отдельном блоке с комментарием //VENDOR, к сожалению в этом проекте верстальщик кинул все стили плагинов в общую папку стилей, поэтому css подключены общей кучей.

Еще момент по функции ShowHead(). В последнее время все стали верстать в манере html5, и соответственно мета тэг кодировки отличается от битриксовского. Чтобы полностью соответствовать верстке я заменил функцию ShowHead() на то что она собственно содержит. Только убрал в этой функции вывод одного мета тэга. В принципе можно и полный meta charset вызывать, такой же как в функции $APPLICATION->ShowHead(), и тогда можно собственно саму эту функцию и вызывать.

Зависимые области

Если на каких то страницах есть боковая панель слева или справа от основного контента, а на каких то страницах этой панели нет, то на мой взгляд панель надо включать в основной шаблон сайта. Не нужно писать html код панели прямо на самой странице. Например, если боковая панель должна быть в разделе «О компании», папка /about/, то не нужно писать html код в файле /about/index.php, в этом файле должно быть только основное содержимое страницы. Это касается не только боковых панелей, но и вообще любых областей сайта которые отображаются и пропадают в зависимости от раздела. Все такие области условно можно назвать зависимыми областями.

Как именно отображать зависимые области? Если речь идет только о главной странице, то достаточно просто хардкодом прописать в глобальном шаблоне условие $APPLICATION->GetCurDir() == ‘/’. Если область должна как то более гибко отображаться, то можно использовать свойство раздела битрикса. Свойство страницы в данном случае не подходят, так как на момент выполнения файла header.php свойство страницы еще не определено, а вот свойство раздела уже есть. Достаточно в настройках модуля управления структурой прописать отдельное свойство под каждую область и в дальнейшем просто включать и отключать область в нужных местах. Если область по умолчанию должна отображаться везде кроме главной страницы, плюс отключена на нескольких выбранных страницах, то определяем свойство раздела show_area_name = Y в корне сайта, и во всех подразделах область будет отображаться, чтобы значение по умолчанию не влияло на главную страницу прописываем в глобальном шаблоне проверку и на свойство и на папку одновременно.

В качестве примера можете посмотреть код шаблона выше, там еще до объявления DOCTYPE у меня собрано свойство show_left_sidebar и текущая директория. Использовать эти собранные переменные можно так:

<?if($show_left_sidebar == 'Y' && $dir != '/'):?>
    <div class="row">
        <div class="col-md-4 col-sm-6">
            <?
            $APPLICATION->ShowViewContent('leftSidebar');
            ?>
        </div>
        <div class="col-md-8 col-sm-6" id="article">
<?endif;?>

Вместо вызова ShowViewContent() можно поставить какую нибудь включаемую область или сразу вызывать нужные компоненты.

Константы

Вы практически наверняка будете использовать инфоблоки. Большая часть задач в битриксе решается на инфоблоках и каталог товаров, и новости, и какие сообщения об акциях и т.д. В компонентах одним из параметров передается инфоблок. Многие инфоблоки используются на разных страницах, или даже на одной странице в нескольких местах. Если вы вдруг по каким то причинам решите использовать другой инфоблок, то придется во всех местах где этот инфоблок используется исправлять параметры компонента. Но можно при старте проекта объявить константы по всем инфоблокам, плюс любые другие значимые данные, которые могут использоваться на разных страницах. И дальше во всех местах где используется ID инфоблока новостей, заменить его на константу с ID этого инфоблока.

Создайте файл /local/php_interface/init.php. Создайте файл /local/php_interface/include/constants.php. В файле /local/php_interface/init.php подключите файл /local/php_interface/include/constants.php через require или include. Таким образом файл констант у нас будет выполняться вообще всегда, при каждом открытии страницы. Что должно быть в файле с константами? Собственно сами константы. Объявляем константы так:

<?php
/**
 * IBLOCK IDs
 */
define("IBLOCK_ID__CATALOG", 4);
define("IBLOCK_ID__OFFERS", 11);
define("IBLOCK_ID__VIDEO", 9);
...
остальные используемые инфоблоки
...
/**
 * PATHS
 */
define('PATH_TO_BASKET', '/personal/order/make/');
define('PATH_TO_ORDER', '/personal/order/make/');

И дальше подставляем константы например в вызов компонента:

<?$APPLICATION->IncludeComponent(
	"bitrix:catalog", 
	"catalog", 
	array(
		"IBLOCK_TYPE" => "catalog",
		"IBLOCK_ID" => IBLOCK_ID__CATALOG,
		[...]
	),
	false
);?>

И теперь если вы например захотите протестировать импорт из 1с в другой каталог, то достаточно будет сделать импорт, и поменять значение в константе. Вообще весь сайт будет брать товары из другого инфоблока и сразу можно будет посмотреть результат.

В том случае когда над проектом работают несколько программистов на разных серверах, либо даже если только один программист собирается перенести функционал с тестового сервера на боевой могут возникнуть проблемы, так как ID инфоблоков могут различаться. Например инфоблоки были созданы в разном порядке, или достаточно всего один раз удалить инфоблок на одном из сайтов, чтобы все последующие инфоблоки даже созданные в верном порядке были под разными ID. При простом копировании вызова компонента будут вызываться разные инфоблоки, то есть например на тестовом выводятся новости из компонента с ID=3, а на боевом инфоблок новостей имеет ID=2. И соответственно при копировании вызова компонента будут не новости отображаться, а какая нибудь фотогалерея.

Чтобы решить проблему с разными ID инфоблоков на разных сайтах константы тоже пригодятся. Достаточно при старте страницы получить инфоблок по его символьному коду и засунуть в константу. Специально для этой цели я написал класс — Класс для получения инфоблока по коду. Здесь я полный листинг файла приводить не буду, там ничего особенного. Вкратце, что там происходит вообще. Если вы пользуетесь моим классом, то объявляем константу вот так

define('IBLOCK_ID__CATALOG', IBlockData::getByCode('CATALOG'));

Далее функция проверяет статическую переменную класса $byCode, если эта переменная пуста, то получает полный список инфоблоков, и записывает в эту переменную массив ID инфоблоков, где ключами массива являются коды инфоблоков. Далее функция смотрит элемент массива с ключом переданным в качестве аргумента функции. Если элемент найден по ключу, то возвращает его значение. Итого функция по коду инфоблока возвращает его ID. Полная выборка инфоблоков кешируется стандартным битриксовским кешем на сутки, то есть запрос к БД будет только при первом обращении, а весь следующий день значение будет браться из кеша. В кеш ложатся только пара символьный код — ID, поэтому функция достаточно легкая. Инфоблоки берутся с привязкой к сайту, то есть класс применим при работе с многосайтовостью, по коду вернется ID инфоблока на конкретном сайте.

Наименование констант

Выше я привел довольно простой файл констант, в котором только несколько инфоблоков и пара путей. Однако же бывают проекты в котором констант на пару экранов. И если называть константы не задумываясь, то будет хаос. Лично я стараюсь обозначать константы по виду. Например если в константе хранится ID инфоблока, то делаю префикс IBLOCK_ID, если там путь, то префикс PATH. В общем тут строгих правил никаких нет, но все же стоит как-то хотя бы минимально обозначать в названии константы ее значение. Константа «TEST_BLOCK» какая-нибудь вообще непонятно что содержит, особенно если там просто цифра записана.

Модуль проекта

Со временем у любого программиста накапливается довольно много готового кода под разные ситуации, который заметно облегчает работу. Кроме того во многих проектах есть сложный функционал, который нужно где-то хранить. Я встречал подключение классов в init.php (как довольно грамотно сделанное с автолоадом, так и простые инклуды), всякие вычисления в result_modifier.php, сам я раньше создавал под проект свой специфический модуль. Однако же сейчас я остановился на создании универсального локального модуля, который уже содержит все наработки и готов к написанию специфичного функционала. На всех проектах я использую модуль «local.lib». Название через точку чтобы он отобразился в списке модулей marketplace. Что именно можно и нужно делать в модуле?

Автолоад классов

На текущий момент битрикс поддерживает автоматический автолоад классов. Тавтология небольшая, но тем не менее. Автолоад классов — подключение класса по требованию. Автоматический автолоад — не нужно прописывать классы в автолоад заранее, путь до файла автоматически определяется при вызове. Что это означает на практике? В папке с модулем создаете папку /lib/, в папке /lib/ создаете файл testecho.php, название обязательно в нижнем регистре. В файле пишете:

<?php
namespace Local\Lib;

class TestEcho
{
    public function test()
    {
        echo 'test';
    }
    
    public static function testTwo()
    {
        echo 'test two';
    }
}

Теперь в любом месте проекта, на любой странице, в любом компоненте и т.д. можете этот свой класс использовать:

<?php
if(\Bitrix\Main\Loader::includeModule('local.lib')) {
	\Local\Lib\TestEcho::testTwo();
	
	$test = new \Local\Lib\TestEcho();
	$test->test();
}

И в месте вызова будет отображаться строка «test», либо «test two» из класса.

Теперь после примера можно чуть подробнее остановиться на том, как работает автолоад классов. Обратите внимание на первую строку в файле с классом «namespace Local\Lib;» именно на основе пространств имен все и работает. Модуль у нас называется local.lib, это означает что все классы модуля должны быть в пространстве имен Local\Lib. Если бы модуль назывался test.module, то мы бы во всех классах прописывали пространство имен Test\Module. При публикации на marketplace битрикса первое слово до наклонной черты — это id партнера, второе слово это название модуля (просто на всякий случай).

Можно использовать подпространства имен. Например Local\Lib\Helpers. Создаете папку /lib/helpers/ и в ней файл increment.php

<?php
namespace Local\Lib\Helpers;

class Increment
{
    public static function get($number)
    {
        return $number++;
    }
}

Обратите на пространство имен, я туда добавил Helpers. И точно так же как и в предыдущем примере используем класс в любом месте

<?php
if(\Bitrix\Main\Loader::includeModule('local.lib')) {
	echo \Local\Lib\Helpers\Increment::get(1);
}

После выполнения кода в месте вызова отобразится циферка «2».

Подробнее для тех кто не понял в чем суть. В модуле битрикса можно создать сколько угодно классов, классы можно красиво разложить по папкам. Класс вообще никак не влияет на производительность, до тех пор, пока к нему не обратились. То есть только в момент обращения к классу срабатывает автолоад, по вызванному имени класса битрикс пытается найти файл, и подключает конкретно этот файл. Например имя класса \Local\Lib\Helpers\Increment означает что битрикс будет смотреть в папку модулей, будет искать в этой папке подпапку local.lib, далее внутри папки local.lib он будет искать lib/helpers/ и внутри этой папки уже будет искать файл increment.php. Если такой файл найден, то он подключается инклудом и вызывается класс из этого файла.

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

Обработчики

Практически во всех битрикс проектах, за редким исключением файл init.php это свалка. Какие то функции, нагромождение классов, тысячи строк кода который непонятно вообще используется или лежит в качестве наследия. Тьма каких то обработчиков, инклудов. В общем смотрится это все довольно ужасно. Чтобы такого хаоса не было стоит хранить и использовать обработчики грамотно. В большинстве моих проектов файл init.php состоит всего из пяти строк

<?php
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();

if (file_exists($_SERVER["DOCUMENT_ROOT"]."/local/php_interface/include/constants.php"))
	require_once($_SERVER["DOCUMENT_ROOT"]."/local/php_interface/include/constants.php");

if (file_exists($_SERVER["DOCUMENT_ROOT"]."/local/php_interface/include/handlers.php"))
	require_once($_SERVER["DOCUMENT_ROOT"]."/local/php_interface/include/handlers.php");

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

<?php

use \Bitrix\Main\Loader;

$eventManager = \Bitrix\Main\EventManager::getInstance();

//page start
AddEventHandler("main", "OnPageStart", "loadLocalLib", 1);
function loadLocalLib()
{
    Loader::includeModule('local.lib');
}


//BASKET
//basket add
AddEventHandler("sale", "OnBeforeBasketAdd", array('Local\Lib\Handlers\Basket', 'beforeAdd'));
AddEventHandler("sale", "OnBasketAdd", array('Local\Lib\Handlers\Basket', 'afterAdd'));

//basket update
AddEventHandler("sale", "OnBeforeBasketUpdate", array('Local\Lib\Handlers\Basket', 'beforeUpdate'));
AddEventHandler("sale", "OnBasketUpdate", array('Local\Lib\Handlers\Basket', 'afterUpdate'));

// basket delete
AddEventHandler("sale", "OnBeforeBasketDelete", array('Local\Lib\Handlers\Basket', 'beforeDelete'));
AddEventHandler("sale", "OnBasketDelete", array('Local\Lib\Handlers\Basket', 'afterDelete'));



//order
AddEventHandler("sale", "OnOrderAdd", array('Local\Lib\Handlers\Order', 'afterAdd'));
AddEventHandler("sale", "OnOrderUpdate", array('Local\Lib\Handlers\Order', 'afterUpdate'));

//property types
AddEventHandler("main", "OnUserTypeBuildList", array('Local\Lib\Properties\Complect', 'GetUserTypeDescription'));
AddEventHandler("iblock", "OnIBlockPropertyBuildList", array('Local\Lib\Properties\Complect', 'GetUserTypeDescription'));


//user
AddEventHandler("main", "OnBeforeUserRegister", array('\Local\Lib\Handlers\User', 'beforeUpdate'));
AddEventHandler("main", "OnBeforeUserUpdate", array('\Local\Lib\Handlers\User', 'beforeUpdate'));

//highload blocks
$eventManager->addEventHandler('', 'UserDataOnUpdate', array('\Local\Lib\Handlers\UserData', 'afterUpdate'));
$eventManager->addEventHandler('', 'UserDataOnAdd', array('\Local\Lib\Handlers\UserData', 'afterAdd'));

Никакого кода здесь нет и не должно быть. Единственное исключение, это функция подключения локального модуля. Чтобы не надо было везде его прописывать, просто сразу пользуемся функциями модуля. Если модуль гарантированно подключен при старте страницы, то писать \Bitrix\Main\Loader::includeModule(‘local.lib’) как в предыдущем примере уже не нужно, сразу вызываем классы модуля и все.

Как вы уже наверное поняли на основе предыдущего блока про автолоад — все обработчики лежат в локальном модуле. Вызов array(‘Local\Lib\Handlers\Basket’, ‘afterDelete’) по событию OnBasketDelete означает, что при необходимости битрикс автоматически подключит файл /local/modules/local.lib/lib/handlers/basket.php, и вызовет статическую функцию afterDelete, класса Basket.

Битрикс позволяет регистрировать обработчики при установке модуля. То есть в файле /install/index.php просто один раз регистрируем обработчик и он начинает работать. При этом в файле handlers.php будет пусто. Для модулей в маркетплейс это безусловно очень удобно, и по сути единственный возможный для них вариант работы. Однако я считаю, что для модуля проекта такого делать не стоит. Во первых, обработчики часто добавляются и удаляются, а каждый раз удалять и устанавливать обратно модуль это вообще не круто, как и постоянно лезть в консоль php. Во вторых, зарегистрированные при установке модуля обработчики фиг найдешь. Про них нужно заранее знать, в то время как обработчики из init.php все программисты лезут проверять в первую очередь. Понять что и где делается гораздо проще.

Класс обработчика

Подробнее о том что должно быть в файле /local/modules/local.lib/lib/handlers/basket.php, и о том как должен строиться класс Local\Lib\Handlers\Basket. В битриксе названия событий достаточно запутанные. Всякие before, onBefore и т.д. Впринципе вызываемую функцию можно назвать просто по названию события. Если событие называется OnBeforeBasketDelete, то в классе Basket так и пишем

<?php
namespace Local\Lib\Handlers;

use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Loader;

Loc::loadMessages(__FILE__);

class Basket
{
	public static function OnBeforeBasketDelete($ID)
	{
		//do something
	}
}

однако логичнее как мне кажется называть функции по шаблону «когдаДействие», например «beforeDelete», «afterDelete», «beforeAdd», «afterChange» и т.д. Класс обработчика предназначен для работы с конкретным объектом (условным), например класс для событий корзины, класс для событий элемента инфоблока, класс для работы с событиями заказа и т.д. Смысла дублировать название класса в названии функции на мой взгляд нет. В этом примере мы работаем с событиями корзины, и соответственно функция которая будет вызываться перед удалением товара из корзины должна называться beforeDelete.

<?php
namespace Local\Lib\Handlers;

use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Loader;

Loc::loadMessages(__FILE__);

class Basket
{
	public static function beforeDelete($ID)
	{
		//do something
	}
}

Все функции событий должны быть статическими. Битрикс не создает объект класса, он просто вызывает одну конкретную функцию. Но использовать класс просто как хранилище функций довольно глупо. Поэтому этот класс мы сделаем паттерном singleton и во всех функциях событий будем получать объект класса. То есть код будет выглядеть вот так:

<?php
namespace Local\Lib\Handlers;

use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Loader;

Loc::loadMessages(__FILE__);

class Basket
{
    /**
     * @var array
     */
    protected $arFields;

    /**
     * @var array
     */
    protected $errors = array();


    /**
     * @var self
     */
    private static $instance;

    private function __construct()
    {
    }

    private function __clone()
    {
    }

    private function __wakeup()
    {
    }

    public static function getInstance()
    {
        if (empty(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public static function beforeDelete($basketItemId)
    {
        $handler = self::getInstance();
        $handler->doSomething();
        $handler->doSomethingElse();

        return $basketItemId;
    }

    protected function doSomething()
    {
        //do something
    }

    protected function doSomethingElse()
    {
        //do something else
    }
}

Кроме того обратите внимание на функции doSomething() и doSomethingElse(), по факту обработчик события вызвался всего один раз, однако в обработчике мы выполнили два логически разделенных действия. В файле handlers.php всего один обработчик на событие OnBeforeBasketDelete, но внутри функции beforeDelete мы вызываем несколько логически не связанных функций. Это тоже значительно увеличивает читабельность файла handlers.php с обработчиками. Внутри функций класса мы уже можем использовать объект $this, как в нормальном полноценном классе, вызывать другие функции класса, использовать переменные класса, получить какие то общие данные (типа состояние элемента до изменения) и использовать их в нескольких разных функциях и т.д. То есть писать какой то уже более менее сложный код.

Следующий пример использования класса чуть посложнее. Если в функции по событию OnBeforeIBlockElementUpdate вернуть false и в $APPLICATION бросить ошибку, то элемент не сохранится. Если в этой же функции изменить какое либо поле, то сохранится уже измененное значение. Допустим мы хотим вообще всем элементам в инфоблоке каталог, в названии добавлять префикс test при сохранении. Кроме того представим, что в инфоблоке каталог у нас есть свойство типа список, с одним значением (галочка да/нет) и кодом READ_ONLY. Если галочка в свойстве READ_ONLY стоит, то элемент не должен сохраниться. Вот так это можно реализовать в классе обработчика:

<?php
namespace Local\Lib\Handlers;

use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Loader;

Loc::loadMessages(__FILE__);

class Catalog
{
    /**
     * @var array
     */
    protected $arFields;

    /**
     * @var array
     */
    protected $arElement;

    /**
     * @var array
     */
    protected $errors = array();


    /**
     * @var self
     */
    private static $instance;

    private function __construct()
    {
    }

    private function __clone()
    {
    }

    private function __wakeup()
    {
    }

    public static function getInstance()
    {
        if (empty(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Выполняется по событиям
     * OnBeforeIBlockElementUpdate
     *
     * @param $arFields
     *
     * @return array|bool
     */
    public static function beforeChange(&$arFields)
    {
        if ($arFields['IBLOCK_ID'] == IBLOCK_ID__CATALOG) {
            $handler = self::getInstance();
            $handler->setFields($arFields);
            $handler->getElement();

            $handler->setName();
            $handler->checkReadOnly();

            if (!empty($handler->errors)) {
                $errors = implode("\r\n", $handler->errors);

                global $APPLICATION;
                $APPLICATION->throwException($errors);
                return false;
            } else {
                $arFields = $handler->arFields;
            }
        }

        return $arFields;
    }

    protected function setName()
    {
        $this->arFields['NAME'] = 'Test '.$this->arFields['NAME'];
    }

    protected function checkReadOnly()
    {
        if(!empty($this->arElement['PROPERTY_READ_ONLY_VALUE'])){
            $this->errors[] = 'Снимите галочку "Только для чтения", чтобы сохранить элемент';
        }
    }

    protected function setFields($arFields)
    {
        $this->errors = array();
        $this->arFields = $arFields;
    }

    protected function getElement()
    {
        if (is_array($this->arFields)) {
            $this->arElement = \CIBlockElement::GetList(
                array(),
                array(
                    'ID' => $this->arFields['ID'],
                    'IBLOCK_ID' => $this->arFields['IBLOCK_ID'],
                ),
                false,
                false,
                array(
                    'ID',
                    'IBLOCK_ID',
                    'PROPERTY_READ_ONLY',
                )
            )
                ->Fetch();
        }
    }
}

Вместо функции setName можно поставить любые преобразования данных.

То есть в переменной класса $errors у нас сохраняются ошибки. Если в любой функции класса объявить ошибку вот так «$this->errors[] = ‘text’;», то при сохранении в админке пользователю отобразится ошибка. Мы можем вызывать сколько угодно функций, вместо свойства READ_ONLY проверить любые другие зависимые данные, может быть даже из нескольких источников и в случае необходимости объявить ошибку с отменой сохранения элемента.

Это два простеньких примера использования класса обработчика. На самом деле возможности тут гораздо шире. Еще например перед удалением элемента можно получить все его поля в переменную класса (напомню, класс singleton, статический класс), а потом уже после удаления просто проверить эту же переменную класса и совершить какие нибудь действия после гарантированного удаления элемента, но с использованием уже удаленных по сути данных.

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

Хэлперы и части страниц

Помимо обработчиков в модуле проекта у меня лежат классы хелперы и часто используемый фукнционал по формированию html (условно части страниц).

Хелперы, это простенькие классы, можно сказать набор функций объединенных в класс. Я часто использую хелпер Files для ресайза и получения изображений (который в отличие от битриксовского всегда возвращает и src, и SRC, плюс еще несколько удобных вещей делает), класс Validation для валидации различных данных типа email, телефонов, ИНН, КПП и т.д., класс Mail для отправки почтовых событий с прикрепленными файлами. Кроме того под проекты довольно часто пишутся свои хелперы, если какой то функционал вызывается из нескольких разных мест.

Части страниц это по сути те же хелперы, но не просто набор функций, а уже что-то более менее взаимосвязанное. Например очень частая задача — отобразить любую картинку из анонса, либо из детальной, либо из свойства инфоблока. Для этого я написал класс Image и вынес его в модуль проекта, пример использования:

<?php
//make detail image
$image = new \Local\Lib\Parts\Image(array(
	'width' => 400,
	'height' => 400
));
$image->addImage($this->arProduct['DETAIL_PICTURE']);
$image->addImage($this->arProduct['PREVIEW_PICTURE']);
$image->addImagesList($this->arProduct['PROPERTIES']['MORE_IMAGES']['VALUE']);
$this->arProduct['DETAIL_PICTURE'] = $image->getFirstResized();

В классе последовательно проверяются все переданные данные, и берется первая найденная картинка. По итогу в $this->arProduct[‘DETAIL_PICTURE’] будут храниться данные по файлу картинки, либо false если ни в одном из указанных мест картинка не была найдена. Если картинка найдена, то она сразу пережмется до указанных размеров.

Другой пример для части страниц — слайдеры. Практически во всех проектах есть слайдеры картинок и как правило в слайдер нужно засунуть не одну, а несколько картинок из разных мест, плюс пережать эти картинки под несколько разных размеров, для превью и для отображения на странице как минимум. Класс слайдера работает так:

<?php
//main slider
$arSizes = array(
    'FULL' => array(
        'width' => 2000,
        'height' => 650
    ),
    'PREVIEW' => array(
        'width' => 200,
        'height' => 100
    ),
);
$slider = new \Local\Lib\Parts\Slider($arSizes);
$slider->addSlide($arResult['DETAIL_PICTURE']);
$slider->addSlidesList($arResult['PROPERTIES']['MORE_PHOTO_SITE']['VALUE']);
$slider->addSlidesList($arResult['PROPERTIES']['MORE_PHOTO']['VALUE']);
$arResult['SLIDER'] = $slider->getSlider();

То есть примерно как с картинкой, указали желаемый массив размеров и на выходе в $arResult[‘SLIDER’] мы получим

  1. $arResult[‘SLIDER][‘ORIGINAL’] массив картинок в полном оригинальном размере
  2. $arResult[‘SLIDER][‘FULL’] массив картинок ужатых до какого-то промежуточного размера
  3. $arResult[‘SLIDER][‘PREVIEW’] массив картинок ужатых до самого мелкого размера

Каждый из массивов содержит все картинки совпадающие по ключу. Картинка $arResult[‘SLIDER][‘ORIGINAL’][0] это та же самая картинка, что и $arResult[‘SLIDER][‘PREVIEW’][0], только с другими размерами естественно. При необходимости можно добавить еще какую то градацию размеров в массив $arSizes

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

Итого по модулю проекта

Помимо хранилища классов модуль проекта можно использовать для хранения глобальных настроек, достаточно закинуть файлик options.php в корень модуля и с помощью класса Options (сделал свой на основе этого) задать массив желаемых параметров. В модуле сразу можно делать классы моделей для работы с ORM битрикса. Можно сделать класс для работы c Highload блоком, то есть вызываем функцию типа так Local\Lib\Map::add($arData); в которую передаем чистые данные, или делаем выборку примерно так же, только вместо add что нибудь типа getByUserId, а все взаимодействие с HL блоком прописано внутри класса. В общем модуль проекта это круто, и я крайне советую вам его использовать. Но использовать разумно, не пихать туда все подряд, всякие мелочи, и наоборот большой функционал с использованием всяких сторонних библиотек можно (нужно?) выносить в отдельные модули.

Компоненты

По устройству типового компонента мне нечего добавить. Как использовать result_modifier.php, component_epilog.php, шаблоны компонентов и т.д. все это можно прочитать в официальных обучающих курсах. Единственное что хочу добавить по компонентам касается файла class.php. В каких случаях писать свой компонент, а в каких использовать стандартный я не буду объяснять, большая часть задач решается стандартными компонентами. Остановлюсь чуть подробнее на написании собственных компонентов.

При написании собственных компонентов стоит полностью отказаться от файла component.php. Если там прям совсем какой то микрофункционал, то может быть и стоит его оставить, и то непонятно зачем. Однако на чуть более серьезных задачах стоит пользоваться классом. Перекрываем родительский метод executeComponent() и все содержимое component.php пишем прямо в этой функции. Плюс вместо разделения смысловых блоков комментариями выносим их в отдельные функции. И читабельность кода заметно повышается. Функция executeComponent() если все из нее вынесено в отдельные логические блоки становится довольно короткой, на экран или в крайнем случае на несколько и ее гораздо легче понять, чем десятки экранов сплошного кода разделенного только комментариями.

В классе можно использовать переменную $this->request для доступа к переменным запроса, в эту переменную пишется объект класса Bitrix\Main\HttpRequest и можно прямо сразу в любой функции класса обращаться к его методам, например $this->request->getQuery(«some_name») или $this->request[«some_name»].

В классе доступна функция $this->setTemplateName(‘name’) которая позволяет прямо на лету изменить шаблон, и шаблон переданный при инициализации компонента перестает учитываться. Это может пригодиться например для сложного пошагового мастера, который в зависимости от предыдущих данных определяет текущий шаг и подключает шаблон с этим шагом. Или например если один компонент обслуживает какой-то front-end функционал состоящий из нескольких связанных окошек, можно в зависимости от запроса отображать нужное окошко из определенного шаблона компонента.

В заранее определенной функции onPrepareComponentParams($arParams) можно сразу провести валидацию переданнных в компонент параметров (она получает на вход то что передано в компонент при вызове) и объявить при необходимости ошибку. Там же можно заполнить массив параметров данными из запроса, опять таки провалидировать их и в дальнейшем уже не к запросу обращаться, а просто смотреть гарантированно верные параметры. Функция onPrepareComponentParams() выполняется до executeComponent(), и если в ней объявить ошибку например в переменную класса $this->errors[], то уже в executeComponent() наличие ошибок проверяется просто по заполненности переменной $this->errors

В общем класс компонента может содержать довольно большой объем кода без вреда для читабельности. Это позволяет шире использовать компоненты при решении различных задач. И встает вопрос о том, в каких случаях использовать модуль проекта, а в каких случаях класс компонента.

Компонент vs Модуль

Все это достаточно субъективно, но на мой взгляд выносить какой либо функционал в модуль стоит только в двух случаях:

  1. Функционал используется в нескольких местах сразу
  2. Тяжелый функционал

Если функционал используется сразу в нескольких местах, то выносить его в модуль стоит чтобы избежать дублирования. Например работа с HL блоками не требует большого объема кода, однако же если какой либо HL блок используется в компоненте и плюс в каких либо событиях, то разумно будет вынести весь функционал работы с ним в отдельный класс модуля, а в компоненте оставить только вызов этого класса. Дублирование кстати говоря не только в рамках одного проекта, но и в рамках нескольких. Если вы один и тот же функционал используете на многих проектах, пусть даже всего один раз за проект, то возможно имеет смысл его вынести в модуль.

Тяжелый это функционал или нет судить вам, на мой взгляд грань — это внешние библиотеки. То есть в компоненте не должно быть подключения внешних библиотек вообще. Если вы используете какую-то внешнюю библиотеку (тот же phpexcel например), то ее практически наверняка стоит вынести либо в модуль проекта, либо вообще в отдельный модуль по работе с этой библиотекой. Если никакие внешние библиотеки не используются, то никаких четких критериев предложить не могу, разве что количество строк. Если число строк кода в компоненте больше 500-1 000, то возможно стоит задуматься о выносе части кода в модуль.

Общий взгляд

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


добавил Шубин Александр 25 Июль, 2016
Рубрика: Уроки


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

  • Александр:

    Спасибо! Очень полезная статья!

  • Максим:

    Пробовали в работе плагин для PhpStorm под названием Bitrix Framework Support?

    • Я про него недавно узнал. Пока что просто поставил, и максимум что заметил пути до /bitrix/header.php перестали подсвечиваться предупреждением. В нем разбираться надо еще, только видео с возможностями в быстром темпе на 10 минут. Но не тормозит, что уже радует. Прошлый плагин для битрикса, который я год или два назад ставил не хило так подвешивал систему

  • Кот Матроскин:

    На гитхабе выложена папка с модулями и документацией по ядру D7 — чем так делать.
    Если инклуд в качестве либы может тогда лучше из существующего проекта, зачем использовать api другой папки модулей?
    Статья дельная, но в мелочах некоторых лично я делаю по другому.

    • 1. В чем именно преимущество папки модулей с гитхаба? Я слышал про что-то такое, но особо не вчитывался.

      2. По поводу скачивания папки модулей из существующего проекта:

      а. Отличий папки модулей из проекта и общей библиотеки в плане кода практически нет. Если конечно битрикс обновляется. Если законсервирован старый битрикс, то безусловно нужна папка модулей проекта, а не общая. В остальном единственный случай когда нужна именно папка модулей текущего проекта — поиск багов в ядре, когда что-то работает не так как должно, то нужно смотреть прям актуальный код, а не старый. Если же папка используется просто для примерного представления внутренних механизмов по ctrl+клик или для автодополнений (чтобы функции не подсвечивались предупреждениями), то хватает и просто общей папки на все проекты

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

      в. Общая папка модулей не участвует в контроле версий вообще и не занимает лишнее место в папке с проектом. В отличии от.

      * * *
      Итого.
      Никаких преимуществ у скачивания папки в конкретный проект я не вижу. По поводу использования папки с гитхаба — не сталкивался. Возможно имеет смысл ее использовать, если вы ссылку кинете или подробнее суть распишете.

  • Не могу не заметить, что вы пытаетесь решать задачи, которые уже давно решены, и наступаете на чужие грабли. Хорошо бы погуглить для начала, перед тем, как публиковать подобные статьи. Внесу ясность:

    Про автокомплит.
    Для чего использовать одну и ту же папку /bitrix/modules/ на все проекты? Это будет ужасно работать в случае, если у вас один проект сделан на редакции Старт, а другой — на Бизнесе. Вы в Старте получите автокомплит по магазину, каталогу, бизнес-процессам и т.д., что будет лишним. К тому же директория /bitrix/modules/ целиком — довольно объемна, и трудно переваривается phpStorm’ом, будут тратиться колоссальные ресурсы на автокомплит. А вот если исключить все лишнее (инсталляторы модулей с компонентами, неиспользуемые модули), то автокомплит будет работать в разы шустрее.
    В дополнение к хранению /bitrix/modules — это должна быть обязательно директория с реальными файлами реального проекта, иначе вы не сможете адекватно пользоваться отладчиком в виду отсутствия реальных файлов.

    Про подключение скриптов и стилей на проекте.
    Не стоит подключать все-все-все в header.php, это плохой вариант. Ну зачем вам на каждой странице карусель? Зачем? Тем боле, если frontend’ер сверстал проект с использованием gulp или еще лучше — webpack. Зарегистрируйте js библиотеки в понятии битрикса на каждую точку входа и подключайте по мере необходимости, это совсем не сложно.

    Про константы.
    Вы намеренно даете константам иной смысл. Константа — это неизменяемое значение. В вашем же случае в зависимости от окружения (продакшн или сайт разработки) идентификаторы инфоблоков будут отличаться, что может внести путаницу для разработчиков.
    Ваш класс для получения идентификаторов инфоблоков — слишком недостаточен. Инфоблоков с кодом CATALOG может быть несколько, и класс будет сбоить. Да и не одними идентификаторами инфоблоков мы оперируем — а как же highload-блоки, группы пользователей, разделы и т.д.? Используйте нормальные решения вроде https://github.com/maximaster/tools.finder или https://github.com/bitrix-expert/tools. Легко подключаются к проекту с помощью composer (кстати, почему про него в статье ни слова)?

    Про автозагрузку.
    Автолоадер из состава ядра битрикса не выдерживает никакой критики опытных разработчиков, и является мертворожденным продуктом. Используйте стандарты, которые проверены годами и десятками тысяч разработчиков, а именно PSR-0/4. И опять же — composer наше все в этом плане. Ничего не мешает использовать свой автозагрузчик в модулях битрикса взамен стандартного.

    Про события.
    На мой взгляд необходимость создания файла с описанием всех обработчиков /local/php_interface/include/handlers.php является рудиментарной. Поэтому я сделал автозагрузчик обработчиков событий, который уже очень давно использую и всем рекомендую
    https://github.com/maximaster/tools.events

    Про модуль проекта.
    Очень частно бывает, что неудобно поддерживать модуль проекта. Необходимость держать в актуальном состоянии инсталлятор/деинсталлятор (а иначе зачем тогда модуль?), следить за компонентами и за тем, чтобы они нормально инсталлировались, переинсталлировать каждый раз при деплое. + не прозрачная схема поддержки актуальности БД, все это становится очень не удобным в дальнейшем сопровождении проекта.

    Про корень проекта.
    Не надо делать корень проекта документ рутом. Это неудобно. В корне проекта со временем появится очень много системных вещей, которые не должны попадать в браузер.

    Вообще говоря, я тоже когда-то писал о структуре проектов на битриксе, и вот пока к такому мнению пришел.
    http://zhurov.me/blog/bitrix-code-storage-iii.html
    Разговаривал с очень большим количеством разработчиков на эту тему и все соглашались со мной, либо уже сами давно пришли к подобной схеме хранения.

    • Вы в Старте получите автокомплит по магазину, каталогу, бизнес-процессам и т.д., что будет лишним.

      И что? Не встречал проблем с этим. Особых пересечений по названиям функций там нет. К тому же проекты на старте, которые требовали бы автокомплит у меня отсутствуют, максимум там сайты визитки с вызовом типовых компонентов

      К тому же директория /bitrix/modules/ целиком — довольно объемна, и трудно переваривается phpStorm’ом, будут тратиться колоссальные ресурсы на автокомплит

      Не встречал с этим проблем. Возможно от компьютера зависит. Если при подключении /bitrix/modules/ у вас тормоза, то попробуйте очистить, да.

      это должна быть обязательно директория с реальными файлами реального проекта, иначе вы не сможете адекватно пользоваться отладчиком в виду отсутствия реальных файлов

      Если отладка внутри битрикса нужна, то да, имеет смысл скачать реальные файлы проекта, о чем я сказал в комментарии выше. Ни разу не приходилось отлаживать файлы ядра, вполне достаточно отладки и в своих файлах, например перед или после вызова API функций ядра. Если ошибка в ядре, то лезть внутрь я не стану скорее всего. Баги мгновенно не исправляются. Так что если что-то серьезноев битриксе обновляется, то обновлять стоит на тестовом сервере. Показателен пример с обновлением интернет магазина в марте, сколько было жалоб от тех кто на рабочем обновил. Про сам факт ошибки я скорее всего в битрикс сообщу, однако детально разбираться с ошибкой, если уже ясно что проблема в ядре, я не буду. И смысла не вижу, все равно мгновенно не исправят, и честно говоря просто лень, своей работы хватает.

      Если вы про xdebug, то я его локально не запускаю. Он стоит на локальной виртуалке.

      Ну зачем вам на каждой странице карусель? Зачем? Тем боле, если frontend’ер сверстал проект с использованием gulp или еще лучше — webpack.

      Файлы js и css кешируются. То есть они загрузятся всего один раз. И эти лишние 5-10кб особенно после gzip никакой роли в скорости загрузки страницы не играют. Если на каких то страницах есть тяжелые скрипты или стили, то их стоит вынести отдельно, о чем я и сказал в статье. Использование gulp еще ни о чем не говорит, я и c gulp видел общий файл скриптов например. Тут уже от квалификации верстальщика зависит.

      Вы намеренно даете константам иной смысл. Константа — это неизменяемое значение.

      В рамках копии сайта она и будет неизменной. В чем проблема?

      Инфоблоков с кодом CATALOG может быть несколько, и класс будет сбоить.

      В каком например случае? Приведите пример, когда требуется несколько инфоблоков с одинаковым символьным кодом. Если речь про многосайтовость, то для многосайтовости мой класс подходит. Если у инфоблоков для нормальной работы должны быть одинаковые символьные коды, то что-то не так с архитектурой на мой взгляд.

      Да и не одними идентификаторами инфоблоков мы оперируем — а как же highload-блоки, группы пользователей, разделы и т.д.?

      Битрикс это на ~50% инфоблоки. Расхождения в ID инфоблоков я встречаю постоянно, особенно если работает несколько разработчиков. Highload блоки по ID брать не стоит я думаю, у них одна из определяющих переменных это символьный код. Группы пользователей тоже не встречал чтобы расходились на разных сайтах. В каком случае может пригодиться ID раздела из символьного кода и т.д. не могу придумать. Так что в большинстве случаев хватит и моего простенького класса. Если вам нужно больше, то ничего против использования прям целых библиотек я не имею.

      Легко подключаются к проекту с помощью composer (кстати, почему про него в статье ни слова)?

      Потому что в рамках битрикса он не актуален. Вот перед вами задача реализовать средний интернет магазин + импорт из 1с + выгрузка на яндекс маркет например. Что именно вы в этом случае подключите к битриксу через композер? Вот прям список из нескольких зависимостей для этого среднего интернет магазина приведите. Если там действительно будет что-то полезное, то возможно я соглашусь что его использование имеет смысл.

      У меня есть несколько проектов на symfony2, я знаю что такое composer и против него ничего не имею. В целом классный инструмент. Но почитал ваши статьи, и на текущий момент у меня впечатления, что вы его используете просто для чувства причастности к большому community, типа все так делают, мировая практика и т.д. Просто потому что это круто, без реальной полезности/необходимости. Возможно я ошибаюсь.

      Автолоадер из состава ядра битрикса не выдерживает никакой критики опытных разработчиков, и является мертворожденным продуктом.

      Что именно вас не устраивает в автолоадере от битрикс? Лично меня в нем не устраивает необходимость все файлы называть в нижнем регистре, после symfony не смог сам понять в чем проблема (особо не разбирался на тот момент), в symfony регистр должен совпадать с именем класса. Но это мелочь. Какие конкретно претензии к автозагрузчику еще есть? Разве что интеграция с композером может нарекания вызвать, но про композер я выше сказал.

      На мой взгляд необходимость создания файла с описанием всех обработчиков /local/php_interface/include/handlers.php является рудиментарной.

      Посмотрел ваш механизм. Вы предлагаете в центр ставить событие, я же предлагаю в центр ставить объект события (корзина, элемент инфоблока, заказ). Лично мне удобнее центрироваться на объекте. В качестве демонстрации удобства предлагаю вам с использованием своего механизма написать функционал, который сработает после удаления товара из корзины и в котором можно оперировать удаленными данными. Если вы такой код приведете с использованием вашего механизма, где во главе угла стоит событие, а не объект, то я тоже буду пользоваться вашим механизмом. Это не какая то демонстрационная абстракция, а реальный случай из моего последнего проекта. На текущий момент ваш вариант мне кажется менее удобным.

      Необходимость держать в актуальном состоянии инсталлятор/деинсталлятор (а иначе зачем тогда модуль?)

      Для структуризации кода, очевидно же. Об этом и статья. Инсталлятор и деинсталлятор не нужны.

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

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

      • Поэтому я сделал автозагрузчик обработчиков событий, который уже очень давно использую и всем рекомендую

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

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

          > И что? Не встречал проблем с этим. Особых пересечений по названиям функций там нет. К тому же проекты на старте, которые требовали бы автокомплит у меня отсутствуют, максимум там сайты визитки с вызовом типовых компонентов
          Вы описываете пример архитектуры. Вашу статью будут находить люди в интернете, и будут делать проекты по аналогиии с вашей статьей. Но потом будут натыкаться на очевидные грабли, которые тут не описаны. Касаемо автокомплита — ваш пример архитектуры уже не будет работать, как минимум, для старта. Точно также он не подойдет для Битрикс24 в коробке. Это говорит о том, что вы занимаетесь сайтами на 1С Битрикс только редакций Бизнес и Малый бизнес. Может быть для вашего случая такой способ подойдет, но подойдет он не для всех.

          > Не встречал с этим проблем. Возможно от компьютера зависит. Если при подключении /bitrix/modules/ у вас тормоза, то попробуйте очистить, да.
          Тестировал на нескольких разных железках с разными конфигурациями (macbook air + OSX El Capitain, win7,8,10 + core i5/16Gb/SSD, и довольно слабый комп с Ubuntu на борту). Ситуация с этим была примерно схожей. Если вы не испытывали проблем, это не значит, что их не испытывают другие.
          Это все равно, что добавить под версионный контроль ядро полностью. Попробуйте как-нибудь на досуге. Git с ума сойдет от такого количества файлов, и будет очень долго выполнять любые операции, от статуса до коммита.

          > Ни разу не приходилось отлаживать файлы ядра, вполне достаточно отладки и в своих файлах, например перед или после вызова API функций ядра.
          Ну, что же, значит вам повезло. Мне, к сожалению, приходится довольно часто лазить по ядру битрикса, чтобы понять, что идет не так. И довольно часто нахожу проблемы именно в ядре которые приходиту помогать сотрудникам битрикса их исправлять.

          > Если ошибка в ядре, то лезть внутрь я не стану скорее всего. Баги мгновенно не исправляются.
          Эти слова еще раз подтверждают, что вам никогда не приходилось делать отказоустойчивые сайты.
          А также это подтверждает, что вы лентяй 🙂 (не в обиду будет сказано, все программисты — лентяи)

          > Так что если что-то серьезноев битриксе обновляется, то обновлять стоит на тестовом сервере.
          А никто и не призывает обновлять на продакшене. Но инструментарий для отладки ядра на тестовой системе тоже должен быть, а вы его намеренно игнорируете, и даже не рекомендуете использовать

          > Файлы js и css кешируются. То есть они загрузятся всего один раз. И эти лишние 5-10кб особенно после gzip никакой роли в скорости загрузки страницы не играют.
          У вас 5-10, на проектах посерьезнее — 100-300. И в больших адаптивных проектах это будет играть серьезную роль.
          Оптимизация всегда имеет значение, по крайней мере пока http20 плотно не вошел в нашу жизнь.

          > Использование gulp еще ни о чем не говорит, я и c gulp видел общий файл скриптов например. Тут уже от квалификации верстальщика зависит.
          Бесспорно, зависит. Но мы же говорим о проектах, которые сделаны грамотно крутыми фронтендерами, поэтому данная проблема скорее всего не стоит.

          > В рамках копии сайта она и будет неизменной. В чем проблема?
          Собственно в том, что в рамках проекта она будет изменяемой. Обычно каждая константа в php сопровождается phpDoc комментарием с описанием смысла константы и значения, которое она содержит. В вашем случае реального значения вы не узнаете ни на одной копии из phpDoc. Вот в этом и проблема. От константы ожидаешь, что она имеет постоянное значение на проекте, но в вашем случае это не так.

          > В каком например случае? Приведите пример, когда требуется несколько инфоблоков с одинаковым символьным кодом. Если речь про многосайтовость, то для многосайтовости мой класс подходит. Если у инфоблоков для нормальной работы должны быть одинаковые символьные коды, то что-то не так с архитектурой на мой взгляд.
          Первое что приходит в голову — вы получили уже готовый работающий проект, сделанный очень плохими разработчиками.
          Пример того, когда это НУЖНО, я не буду. Просто потому, что не знаю, когда это нужно. Но вот то, что такое ВОЗМОЖНО и вполне МОЖЕТ БЫТЬ — это я вам точно говорю, битрикс не запрещает в рамках разных типов создавать инфоблоки с одинаковыми кодами по своим причинам. Поэтому такую ситуацию нужно обрабатывать. Если проблема может случиться, она обязательно рано или поздно случится.

          > Битрикс это на ~50% инфоблоки.
          Не соглашусь. Опять же, сказывается ваш недостаток опыта. На небольших проектах — да, инфоблоки играют большую роль. Но мне вот известны примеры проектов, на которых чуть меньше, чем полностью, отказались от инфоблоков в пользу своих таблиц + ORM из D7, и это реальный кейс, который работает, причем довольно шустро по сравнению с инфоблоками. Инфоблоки — это монструозный модуль, который все никак не переведут на D7 из-за его чрезмерной запутанности и несогласованности.

          > Расхождения в ID инфоблоков я встречаю постоянно, особенно если работает несколько разработчиков. Highload блоки по ID брать не стоит я думаю, у них одна из определяющих переменных это символьный код. Группы пользователей тоже не встречал чтобы расходились на разных сайтах. В каком случае может пригодиться ID раздела из символьного кода и т.д. не могу придумать. Так что в большинстве случаев хватит и моего простенького класса.
          А причем тут расхождения в зависимости от проектов? Я вам говорю о том, что битрикс обязывает вас в некоторых случаях для работы API использовать идентификаторы разных сущностей. Например, вы занимаетесь продажей прав, и у вас есть 120 групп пользователей. Чтобы выбрать людей по группе, вам нужно в метод поиска пользователей отдать идентификатор группы. Чтобы получить этот идентификатор, вам придется дополнительно запросить его из БД, причем делать это придется каждый раз. Будете заводить 120 констант? Я — нет, потому и написал свою мини библиотеку для доступа к таким данным.
          То же самое и с Highload-блоками, и с любыми другими сущностями, к которым может потребоваться обращение по ID.

          > Про composer
          Открываю первый попавшийся проект, и сразу цитирую вам перечень модулей, которые подключены через composer:
          monolog/monolog
          maximaster/tools
          maximaster/tools.orm
          maximaster/tools.events
          maximaster/tools.twig
          raveren/kint
          notamedia/console-jedi
          phpoffice/phpexcel
          lox/xhprof
          digitalwand/digitalwand.admin_helper
          symfony/console
          composer/installers
          arrilot/bitrix-migrations

          И еще много много всего. Я не понимаю смысла всех ваших высказываний про composer, т.к. они не имеют смысла вообще никакого. Без composer в любом php проекте сейчас делать вообще нечего. Это не зависит от того, используете вы битрикс или нет.

          > Что именно вас не устраивает в автолоадере от битрикс?
          Эмм … все меня не устраивает в автолоадере. Он примитивен, он содержит имена файлов в нижнем регистре, он заставляет хранить файлы только в модуле (который должен быть установлен через БД!!!), он заставляет именовать сущности не так, как называются классы (ORM и Table). Последнее, кстати, ведет вот к таким ИДИОТСКИМ казусам в ядре битрикса — https://github.com/maximaster/tools.events/issues/1#issuecomment-236638029
          А вот автозагрузчик PSR-4 лишен всех этих недостатков и неявностей и ничего не мешает использовать его в битриксе. Поэтому мой выбор — PSR-4.

          > Разве что интеграция с композером может нарекания вызвать, но про композер я выше сказал.
          Кстати говоря, композеру глубоко пофигу на то, каким способом загружаются классы в битриксе. Он сможет обработать любой случай. Есть очень много библиотек в packagist, которые не поддерживают стандартов PSR-0/4, но они успешно подключаются через composer. Composer просто сглаживает этот недостаток и позволяет разработчику использовать единый интерфейс. Поэтому я не вижу смысла в ваших претензиях к связке bitrix+composer, то, чему вы учите — не правильно.

          > Посмотрел ваш механизм. Вы предлагаете в центр ставить событие, я же предлагаю в центр ставить объект события (корзина, элемент инфоблока, заказ).
          С помощью моей библиотеки вы можете поставить в центр и то, и другое. Зависит от варианта использования.

          > В качестве демонстрации удобства предлагаю вам с использованием своего механизма написать функционал, который сработает после удаления товара из корзины и в котором можно оперировать удаленными данными. Если вы такой код приведете с использованием вашего механизма, где во главе угла стоит событие, а не объект, то я тоже буду пользоваться вашим механизмом.
          Это вполне очевидный кейс, который можно реализовать с помощью моей библиотеки довольно удобно по сравнению с нативным в битриксе исполнением. Код приводить не буду, т.к. вы уже нашли эту возможность самостоятельно. Возможности библиотеки, на самом деле, гораздо шире.

          > Для структуризации кода, очевидно же. Об этом и статья. Инсталлятор и деинсталлятор не нужны.
          А как же вы устанавливаете модуль в проект? Если модуль не установить, он работать не будет. Держать инсталлируемый модуль только ради автозагрузки — считаю бессмысленным, т.к. можно (и нужно) обойтись и без модуля.
          А что если ваш заказчик полезет в список модулей и деинсталлирует модуль случайно/специально ночью? Вам начнут звонить, поднимать вас из кровати в 2 часа, и вам придется модуль как-то установить заново. Но вот как это сделать без инсталлятора? 🙂 Правильно, ручками….

          > Системных вещей типа композера?
          Директория с репозиторием проекта, конфиг composer + папочка vendor, конфиг gulp/webpack + зависимости node.js, bower, конфиг для continuous integration, директория с миграциями проекта. И это не все … 🙂

          > Вот кстати отличный пример, когда ради композера пришлось проект переделывать с этим выносом в поддиректорию, придется настройки веб сервера усложнять и объяснять разработчикам как там все устроено.
          Ради одного композера совсем необязательно переделывать структуру проекта. Зависимости composer можно впихнуть в /local, например, предварительно закрыв доступ к /vendor с помощью конфигов веб-сервера.
          Но даже если вы меняете структуру файлов и папок проекта, то чем усложняются настройки веб-сервера? Вы вообще представляете, как настраивается веб-сервер? Это лишь смена document_root, одна правка одного конфига. И ВСЕ! Дел на 5 минут.

          > Приведите пожалуйста еще несколько полезных зависимостей композера которые вы бы к типовому интернет магазину применили
          Привел небольшую кучку, но по сути можно подключить любой модуль, любой репозиторий. Opensource решений сейчас хватает, и есть очень много полезных, о которых вы просто не знаете (уж не знаю почему — видимо из-за лени 🙂 )

          PS. Спасибо за подробный комментарий, но вы меня НЕ убедили использовать ваш подход к построению архитектуры, т.к. он недостаточно продуман и содержит явные изъяны, о которых я подробно написал.

          PPS. Сорри за капс. С помощью капса пытался выделить сообщение (аналог жирного шрифта).

          PPPS. Оставил свой email в надежде увидеть сообщение на почту об ответе на мой комментарий, однако письма никакого не пришло 🙁

  • Наконец то появилось свободное время чтобы ответить 🙂 На ответ уходит много времени, к сожалению не получалось никак собраться.

    Вы описываете пример архитектуры. Вашу статью будут находить люди в интернете, и будут делать проекты по аналогиии с вашей статьей. Но потом будут натыкаться на очевидные грабли, которые тут не описаны.

    Именно. Для того и статья. Предложение функций от бизнеса в старте — это не грабли. Это мелкое неудобство, с которым на практике вы даже не столкнетесь. Названия классов из бизнеса и старта редко пересекаются. И даже если столкнется кто-то с этим неудобством, то я не вижу в этом ничего плохого. Ну нажмет человек лишний раз стрелочку вниз, чтобы следующую функцию из подсказки выбрать, что в этом такого?

    Тестировал на нескольких разных железках с разными конфигурациями (macbook air + OSX El Capitain, win7,8,10 + core i5/16Gb/SSD, и довольно слабый комп с Ubuntu на борту). Ситуация с этим была примерно схожей. Если вы не испытывали проблем, это не значит, что их не испытывают другие.

    Безусловно я пишу о своем опыте. И я написал, что у меня никаких тормозов при подключении папки модулей как внешней библиотеки нет. Вы написали о своем. Теперь человек прочитавший статью будет выбирать, подключить папку модулей как внешнюю библиотеку, либо ложить папку модулей в проект. Очищать или не очищать. Быстрее будет работать все, ну я рад. У меня с внешней папкой никаких проблем. Кстати i7 стоит, тоже SSD и 16gb DDR4

    Ну, что же, значит вам повезло. Мне, к сожалению, приходится довольно часто лазить по ядру битрикса, чтобы понять, что идет не так. И довольно часто нахожу проблемы именно в ядре которые приходиту помогать сотрудникам битрикса их исправлять.

    Лазить по ядру и мне приходится. Вы же говорите именно про отладку ядра, то есть поиск ошибок в ядре, если я верно вас понял. И честно говоря я не вижу в этом смысла. Если ошибка именно в классах модуля, то править ее все равно не стоит. При первом же обновлении это все затрется и вся работа зря. Если явно видно, что проблема в ядре, то в любом случае придется писать в техподдержку.

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

    Нет. Я не рекомендую его использовать локально. Лично у меня локально лежат только файлы проекта, а не полная копия сайта. Инструментарий для отладки либо на локальной, либо на удаленной тестовой виртуалке стоит ставить. Лично мне так удобнее. Вы предлагаете вообще все для отладки ставить локально? Ну если вам так удобнее, пожалуйста. Не понимаю, почему все должны именно так как вы делать.

    Файлы js и css кешируются. То есть они загрузятся всего один раз. И эти лишние 5-10кб особенно после gzip никакой роли в скорости загрузки страницы не играют.

    У вас 5-10, на проектах посерьезнее — 100-300. И в больших адаптивных проектах это будет играть серьезную роль.
    Оптимизация всегда имеет значение, по крайней мере пока http20 плотно не вошел в нашу жизнь.

    Перечитайте статью пожалуйста. Где я там говорю, что вообще все надо пихать в шаблон? Я специально сделал оговорку, что большие файлы js и css стоит все же включать на нужных страницах. Приведите мне пожалуйста пример сайта, где на какой то отдельной странице js и css больше на 300кб после gzip. Без сжатия это мегабайт текста. Мегабайт скриптов и стилей нужных только на одной конкретной странице. Я правда рад что вы разрабатываете такие крутые сайты, это по сути уже аналог интерфейса gmail по сложности.

    Но мы же говорим о проектах, которые сделаны грамотно крутыми фронтендерами, поэтому данная проблема скорее всего не стоит.

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

    Вот в этом и проблема. От константы ожидаешь, что она имеет постоянное значение на проекте, но в вашем случае это не так.

    Ну вот узнали вы циферку инфоблока каталога. Например эта циферка 3 на одном проекте, и 4 на другом. Что это вам дает? Ну правда. Придирку к сути констант в общем не засчитываю. В рамках копии проекта константа всегда будет константой. Никакого искажения сути нет.

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

    Прочитайте пожалуйста название статьи 🙂 Речь про старт проекта. Про получение уже готового кода я ни слова не говорил.

    Но мне вот известны примеры проектов, на которых чуть меньше, чем полностью, отказались от инфоблоков в пользу своих таблиц + ORM из D7

    Более того, я даже разрабатывал такие проекты 🙂 И это не отменяет того, что битрикс это на 50% инфоблоки. Понятно что я преувеличил. Но не скажу что намного. Битрикс это система управления контентом, и для большинства сайтов контент которым нужно управлять это именно инфоблоки + текстовые страницы.

    А причем тут расхождения в зависимости от проектов? Я вам говорю о том, что битрикс обязывает вас в некоторых случаях для работы API использовать идентификаторы разных сущностей. Например, вы занимаетесь продажей прав, и у вас есть 120 групп пользователей. Чтобы выбрать людей по группе, вам нужно в метод поиска пользователей отдать идентификатор группы. Чтобы получить этот идентификатор, вам придется дополнительно запросить его из БД, причем делать это придется каждый раз. Будете заводить 120 констант? Я — нет, потому и написал свою мини библиотеку для доступа к таким данным.
    То же самое и с Highload-блоками, и с любыми другими сущностями, к которым может потребоваться обращение по ID.

    При том, что этот класс используется именно для создания констант инфоблоков. Вы же пытаетесь натянуть сову на глобус, и представить его как универсальную штуку которую везде надо использовать. Вы написали свою библиотеку для получения групп по символьному коду и я рад. В данной же статье я привел пример класса, который нужен ровно для одной цели — получить ID инфоблока по символьному коду для подстановки в константу. Если мне потребуется что-то более функциональное под конкретный проект я в состоянии усложнить функционал 🙂 Может быть и вашу библиотеку использую, реклама это хорошо 🙂

    Открываю первый попавшийся проект, и сразу цитирую вам перечень модулей, которые подключены через composer:

    Пробежался по списку. Треть модулей ваш собственный код, который вы засунули отдельными зависимостями в композер. Точно так же их можно и в модуль битрикса засунуть. Еще треть я так понимаю для отладки. Для готового проекта они не нужны. Треть условно полезных. Гм. Ну может быть. Вы зародили сомнения по поводу использования composer в битрикс.

    Без composer в любом php проекте сейчас делать вообще нечего. Это не зависит от того, используете вы битрикс или нет.

    Зависит. Вы излишне категоричны.

    А как же вы устанавливаете модуль в проект? Если модуль не установить, он работать не будет. Держать инсталлируемый модуль только ради автозагрузки — считаю бессмысленным, т.к. можно (и нужно) обойтись и без модуля.

    А можно обойтись и без композера 🙂 Например модулем.
    Инсталлятор нужен ровно для одной цели — регистрации модуля в системе. Чтобы заработало автодополнение, да. Чтобы опции подтянулись в разделе настроек еще может быть.
    По сути инсталлятор вообще для всех сайтов одинаковый, и он содержит ровно одну функцию — регистрацию модуля в системе. От проекта в проект там только название в lang файле возможно придется менять. И больше ничего. Инсталлятор не нужен в том плане что ничего там не делается вообще, нечего готовить в нем.

    А что если ваш заказчик полезет в список модулей и деинсталлирует модуль случайно/специально ночью?

    Значит ССЗБ. При установке и удалении модулей нужно понимать, что и зачем ты делаешь. А что если у вас заказчик полезет и папку vendor удалит? Разговор из той же серии.

    Вы вообще представляете, как настраивается веб-сервер? Это лишь смена document_root, одна правка одного конфига. И ВСЕ! Дел на 5 минут.

    Битриксовская система резервного копирования не будет работать, например. Или на все файлы выше document_root стоит забить? Или забить на резервное копирование от битрикс? Сменить document_root действительно не долго, всем рассказывать о том как теперь в проекте работать — уже дольше.

    Opensource решений сейчас хватает, и есть очень много полезных, о которых вы просто не знаете (уж не знаю почему — видимо из-за лени )

    А возможно потому, что они не так уж и нужны на большинстве проектов 🙂

    PS. Спасибо за подробный комментарий, но вы меня НЕ убедили использовать ваш подход к построению архитектуры, т.к. он недостаточно продуман и содержит явные изъяны, о которых я подробно написал.

    И вам спасибо. Я правда рад услышать про другие подходы, о чем в начале статьи явно написал. Вы меня тоже не убедили прям, но заставили задуматься. Из общения я вынес для себя две главные вещи — возможно стоит использоватье composer и возможно стоит задуматься о выносе document_root в подпапку. Это действительно полезно. Окончательного решения еще не принял. Плюс несколько интересных ссылок. Круто что у вас есть системный подход к организации проекта, и правда интересно читать о других системах организации, однако вам все же стоит более критично смотреть на себя и чаще сомневаться 🙂

    PPPS. Оставил свой email в надежде увидеть сообщение на почту об ответе на мой комментарий, однако письма никакого не пришло

    С письмами беда, да. Надо будет настроить, но честно говоря руки до блога все не доходят 🙂 Это все же просто хобби. Специально пришлю личное уведомление 🙂

    P.S. Эх. Вот вроде нифига не делаешь, просто ответ в бложик, а почти два часа потратил. Блин)

  • Предисловие.
    Перечитал уже то, что написал, и понял, что в некоторых комментариях могу быть излишне резок или нетактичен. Не воспринимайте близко к сердцу, у меня эмоции.

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

    > Именно. Для того и статья. Предложение функций от бизнеса в старте — это не грабли. Это мелкое неудобство, с которым на практике вы даже не столкнетесь.
    Нужно четко понимать, к чему может привести каждое такое мелкое неудобство. Если для вас это мелкое неудобство, то для других это неудобство может стать бессмысленной потерей времени. Поэтому я стараюсь избегать подобных вещей.

    > Названия классов из бизнеса и старта редко пересекаются.
    Названия классов — не пересекаются в принципе, дело в другом. Неопытный разработчик может очень долго вдуплять, почему в автокомплите у него есть такой класс/метод, в документации на битрикс есть такой класс/метод, а вот в коде он не работает вообще. Может пройти полчаса, час, прежде чем он обратится к более опытному коллеге за помощью, или осознает, что нужного модуля нет в системе. Все это приводит к потере времени, как этого начинающего разработчика, так и вашего (если он обратился к вам в пятницу вечером со своим вопросом).

    > И даже если столкнется кто-то с этим неудобством, то я не вижу в этом ничего плохого. Ну нажмет человек лишний раз стрелочку вниз, чтобы следующую функцию из подсказки выбрать, что в этом такого?
    Ничего плохого в этом нет. Только пустая трата времени, и все. Пускай люди учатся на своих ошибках, все равно большинство не умеет учиться на чужих. Вы пропагандируете именно такой подход, как я понимаю.

    > Если ошибка именно в классах модуля, то править ее все равно не стоит. При первом же обновлении это все затрется и вся работа зря. Если явно видно, что проблема в ядре, то в любом случае придется писать в техподдержку.
    Это все субъективно. Когда вы находите ошибку в ядре и можете уговорить своего заказчика умерить свой аппетит — это одно. Но когда подобное происходит в большом бизнесе — бизнесу дешевле сменить подрядчика, чем пойти на ограничения платформы.
    Простой пример — бизнес затеял какую-то беспрецедентную акцию, которая принесет ему 100500 миллионов дохода. А потом за 2 дня до запуска акции выясняется, что ИТ руководитель бизнеса не учел, что битрикс работает на самым очевидным образом, а по своей, никому неведомой логике (я щас про правила работы корзины говорю конкретно, буквально на днях случай был). Повлиять на поведение за пределами ядра в таком случае практически нельзя, и гораздо дешевле исправить ошибку в поведении именно в ядре, сделав там небольшой фикс (пускай и временный), а ИТ руководителю дать по лбу за такие проволочки.
    К тому же если наладить адекватную работу с исходниками ядра, то можно избежать многих проблем, в т.ч. и с обновлением этого самого ядра.

    > Нет. Я не рекомендую его использовать локально. Лично у меня локально лежат только файлы проекта, а не полная копия сайта. Инструментарий для отладки либо на локальной, либо на удаленной тестовой виртуалке стоит ставить. Лично мне так удобнее.
    Статья называется «Правильный старт и развитие bitrix проекта», а не «Мой опыт старта и развития bitrix проекта». Вы пытаетесь личный опыт подать за «правильный» вариант.
    «Правильного» варианта в понятии современных технологий веб-разработки для Bitrix Framework не существует, и не будет его еще очень долго, т.к. команда разработки Битрикса не нацелена на технологии, она нацелена только на бизнес. И разработчики Bitrix Framework, похоже, сами не осознают всей глубины проблемы, которую они создают сообществу разработчиков.

    > Перечитайте статью пожалуйста. Где я там говорю, что вообще все надо пихать в шаблон? Я специально сделал оговорку, что большие файлы js и css стоит все же включать на нужных страницах.
    Ок, оговорка, так оговорка. Просто посмотрел на пример кода, и увидел, что там все в шаблоне, а на оговорку особого внимания не обратил. Извинтиляюсь.

    > Приведите мне пожалуйста пример сайта, где на какой то отдельной странице js и css больше на 300кб после gzip. Без сжатия это мегабайт текста. Мегабайт скриптов и стилей нужных только на одной конкретной странице.
    Зайдите на любой крупный ecommerce проект, или на любой сайт крупного банка. Для примера — mvideo.ru, главная страница — 923kb javascript и 251kb css (и это уже после gzip). Взять любой средний SPA проект, так там может и больше быть, гораздо больше.
    Сайт правительства Москвы — https://www.mos.ru/. Там вообще css+js весит больше 2х Мб на главной.
    Примеров можно найти довольно много, если захотеть.

    > Ну вот узнали вы циферку инфоблока каталога. Например эта циферка 3 на одном проекте, и 4 на другом. Что это вам дает? Ну правда. Придирку к сути констант в общем не засчитываю. В рамках копии проекта константа всегда будет константой. Никакого искажения сути нет.
    Вы опять размышляете со своей позиции. Я бывал в ситуациях, когда вот из-за таких констант люди тратили 30-60 минут на разбор полетов. Да, может быть из-за своей неквалифицированности, но не это важно. Важно то, что время было потрачено впустую из-за подмены понятий. Я не буду дискутировать на эту тему. Вы рано или поздно столкнетесь в своей практике с такой ситуацией и вспомните мои слова.

    > Прочитайте пожалуйста название статьи Речь про старт проекта. Про получение уже готового кода я ни слова не говорил.
    Прочитал. Есть слова «Старт и Развитие». Развивать можно не только с нуля. Ну и опять же, в названии статьи есть слово «Правильный». В мире битрикса словосочетание «Правильный старт» или «Правильное развитие» является оксюмороном, ИМХО. А оно происходит именно так, потому что Best practices из мира битрикса никак не соответствую best practices из остального мира php разработки. Они противоречат друг другу. Если весь мир следует одному тренду, а битрикс другому — то 99,9(9)% с битриксом непорядок. Рыжиков может заявить, что битрикс — это феномен, эдакий «гений» в современном мире разработки, но он явно будет не прав … уж с технической стороны точно.

    > При том, что этот класс используется именно для создания констант инфоблоков. Вы же пытаетесь натянуть сову на глобус, и представить его как универсальную штуку которую везде надо использовать.
    Вы некорректно поняли мои предыдущие комментарии на эту тему. Речь совсем не о том, как я воспринял ваш класс. Речь о том, что вы НЕ пытаетесь создавать решения, которые просто реиспользовать и развивать, и пытаетесь публиковать этот класс под видом как раз такого решения.
    Я вам толкую о том, что задача, которую вы решаете своим классом, уже давно решена, а вы пытаетесь распространять свой велосипед. Нет, в велосипедах нет ничего плохого, даже наоборот, они отлично помогают разобраться в теме. Но мы же про «правильный старт и развитие», так ведь? Зачем нам в «правильном» проекте велосипеды?

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

    > В данной же статье я привел пример класса, который нужен ровно для одной цели — получить ID инфоблока по символьному коду для подстановки в константу.
    И эта задача уже решена. И решена более удачным способом, нежели решили ее вы. Вот и все, что я хотел до вас донести.

    > Если мне потребуется что-то более функциональное под конкретный проект я в состоянии усложнить функционал
    Усложните, и вам придется скопировать вручную ее во все свои проекты. А потом вы обнаружите, что в вашей библиотеке будет ошибка, и во всех ваших проектах придется вручную ее исправлять методом «копипасты». Мама дорогая … это будет напрягать, если проектов хотя бы больше пяти.

    >> Без composer в любом php проекте сейчас делать вообще нечего. Это не зависит от того, используете вы битрикс или нет.
    > Зависит. Вы излишне категоричны.
    И все же — не зависит. Я не помню ни одного проекта, на котором бы мне не пришлось подключить какой-то внешний модуль, который не имеет отношения к битриксу. Самый простой, а по совместительству — самый удобный способ сделать это — подключить через composer. И я не вижу никакого смысла в вашем сопротивлении этой технологии. Composer — это один из самых продвинутых на сегодняшний момент менеджеров зависимостей не только в мире php (в php по сути и альтернатив-то нет), но и вообще в мире. И как минимум глупо отказываться от его возможностей. Я даже ради PSR-4 автозагрузчика буду подключать composer на проект, и это не будет являться оверхедом.

    > А можно обойтись и без композера Например модулем.
    Ну так-то можно и без модуля, и без композера обойтись одновременн 🙂 чо уж там .. на худой конец можно и без битрикса обойтись. Хотя, если делать проект без битрикса, то без композера уже не обойтись точно.

    > Инсталлятор нужен ровно для одной цели — регистрации модуля в системе. Чтобы заработало автодополнение, да. Чтобы опции подтянулись в разделе настроек еще может быть.
    > По сути инсталлятор вообще для всех сайтов одинаковый, и он содержит ровно одну функцию — регистрацию модуля в системе. От проекта в проект там только название в lang файле возможно придется менять. И больше ничего. Инсталлятор не нужен в том плане что ничего там не делается вообще, нечего готовить в нем.
    И опять же сказывается отсутствие опыта работы с серьезными проектами. Инсталлятор для такого «центрального» модуля системы может обрастать довольно обширным функционалом. Примеры приводить не буду, когда вы расширите свой кругозор, тогда поймете. И я все же не об этом. Я о том, что использование модуля в битриксе является избыточным в большинстве случаев, если на проекте используется composer. А использование composer на проекте с битриксом очень сложно назвать «избыточным», т.к. он таковым не является

    > Пробежался по списку. Треть модулей ваш собственный код, который вы засунули отдельными зависимостями в композер. Точно так же их можно и в модуль битрикса засунуть.
    Конечно мне удобнее выносить свой код в библиотеки для composer, т.к. процесс их распространения и поддержки упрощается в x10 и более раз, это очевидно. И это лишь первый попавшийся проект, который я открыл среди своего списка, чтобы скинуть вам список его зависимостей. Есть проекты, которые используют по 20-30 библиотек, не входящих в состав битрикса. Если бы composer’а не было, мне пришлось бы ломать голову, как их встроить в проект и удобно обновлять, а тут мне даже думать об этом не приходится, они сами за себя все делают

    > Еще треть я так понимаю для отладки. Для готового проекта они не нужны.
    Статья про «Старт и развитие», а не про «готовые проекты», цитирую вас 🙂 .
    Как вы собираетесь разрабатывать проект с нуля, или развивать его без отладки? Вы что, не выводите отладочные сообщения, не пользуетесь профилировщиком и отладчиком? Мне вас жаль

    > Треть условно полезных. Гм. Ну может быть. Вы зародили сомнения по поводу использования composer в битрикс.
    Это какие из них условно полезные?
    PHPExcel — самая популярная библиотека для генерации и чтения Excel документов. Это она условно полезная?
    symfony/console — самое удобное решение для организации cli интерфейса, это он условно полезный?
    Monolog — самое используемое решение в мире php для генерации логов, один из немногих, который следует стандарту PSR-3 — это тоже «условно-полезная» библиотека?
    Я думаю, вам стоит больше изучать современные подходы из мира php, вы явно от них отстаете, нужно наверстывать!

    > Значит ССЗБ. При установке и удалении модулей нужно понимать, что и зачем ты делаешь. А что если у вас заказчик полезет и папку vendor удалит? Разговор из той же серии.
    Да, буратины злобные. И чем богаче, тем злобнее.
    Про vendor — если заказчик удалит директорию vendor, то ее восстановление — дело одной команды в cli, которая широко известна и документирована — composer install. Если же заказчик удалит модуль с ключевой функциональностью проекта, то я не уверен, что у вас и админка-то будет работать, чтобы этот модуль установить заново. А еще я не уверен, что у вас инсталлятор и деинсталлятор работают корректно. Делайте выводы.

    > Битриксовская система резервного копирования не будет работать, например. Или на все файлы выше document_root стоит забить?
    А git вам зачем? Вы же пользуетесь git? Конечно пользуетесь. Вот и используйте git для контроля своего кода. А дамп базы и ядра отдайте битриксу, с этим он справиться в состоянии (хоть и не в 100% случаев, у меня до сих пор в моем аккаунте на 1с-bitrix.ru висят баги по системе резервного копирования, которые не исправляются годами)

    > Или забить на резервное копирование от битрикс?
    Эта идея не кажется мне такой уж бредовой, учитывая мой опыт работы с ней.

    > Сменить document_root действительно не долго, всем рассказывать о том как теперь в проекте работать — уже дольше.
    Аа, вот теперь вы начали думать о других 🙂 Это уже хорошо, т.к. по предыдущим комментам это было не так очевидно. Так вот, другие вам спасибо за это скажут. А особенное спасибо вам скажет пентестер, который не найдет дыр в безопасности вашего проекта, а на больших проектах это дорогого стоит.
    Не понимаю, почему для вас и ваших коллег это является новостью. Сам же битрикс в своей же вирт. машине использует такой подход.

    > А возможно потому, что они не так уж и нужны на большинстве проектов
    Может быть для вас оно и так. Ну что ж .. пускай так. Придет время, и вы все поймете

    > Вы меня тоже не убедили прям, но заставили задуматься.
    Значит я не зря тратил время на написание ответов! И это супер.

    > Из общения я вынес для себя две главные вещи — возможно стоит использоватье composer и возможно стоит задуматься о выносе document_root в подпапку. Это действительно полезно.
    Даже не сомневайтесь. Пройдет 2 недели, и вы почувствуете огромный профит от всего этого. А также от еще кучи всего, что предлагает сообщество разработчиков, к которому вы не прислушиваетесь пока, хотя стоило бы. Почитайте про PSR стандарты, про composer. Я лично никак не могу понять, если у вас есть несколько проектов на Symfony, почему вы до сих пор так активно защищаете модули битрикса, которые противоречат всем современным принципам, на которых построен Symfony, Laravel, Yii или любой другой современный php фреймворк.

    Удачи вам в ваших начинаниях, и старайтесь не изобретать велосипедов.

  • Есть ощущение, что вы статью не читали. Посмотрели по диагонали, возмутились что нет композера и решили возмущение выразить. Серьезно. Слишком много снисхождения 🙂

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

    Есть какая то грань до которой я готов разжовывать информацию. Так можно дойти до объяснений по открывающим тэгам php. У кого то может много времени уйти, прежде чем он поймет, что php код работает только внутри определенных тэгов. Будем это тоже пояснять?

    и гораздо дешевле исправить ошибку в поведении именно в ядре

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

    Вы пытаетесь личный опыт подать за «правильный» вариант.

    «Правильного» варианта в понятии современных технологий веб-разработки для Bitrix Framework не существует

    Вы тут никакого противоречия не видите? Понятно что правильного варианта «вообще» нет. Безусловно я рассказываю правильный опыт разработки с моей точки зрения. Я рассказываю неправильно, но правильного и нет. Супер 🙂 Мне нравится логика.

    Для примера — mvideo.ru, главная страница — 923kb javascript и 251kb css (и это уже после gzip)

    Угу. И после открытия перейдите на любую категорию товаров. Браузерный кеш отключать не нужно. Смотрим
    1. Главная страница, галочка «Disable cache» стоит
    Главная страница мвидео
    Загрузилось 872кб скриптов.

    2. Снимаем галочку «Disable cache» и переходим на любую страницу
    Вторая страница мвидео
    Подгрузилось еще 15кб скриптов.

    Ну молодцы конечно, оптимизировали немного, но где здесь 100-300кб о которых вы говорите? Этот пример как раз больше к моей точке зрения подходит. Большая часть скриптов используется вообще на всех страницах, и на некоторых подключены свои специфичные скрипты.

    Сайт правительства Москвы — mos.ru. Там вообще css+js весит больше 2х Мб на главной.

    Сайт написан на ангуляре. Там не столько скрипты, сколько контент подгружается. Тот кто пишет на ангуляре я думаю понимает что именно он делает и где какие скрипты подключать. И вы похоже опять не видите разницу между общим объемом скриптов, и объемом скриптов нужным для конкретной страницы.

    Best practices из мира битрикса никак не соответствую best practices из остального мира php разработки. Они противоречат друг другу. Если весь мир следует одному тренду, а битрикс другому — то 99,9(9)% с битриксом непорядок.

    Нет никакого общего тренда. Везде все делается по разному. Вы на мой взгляд совершаете две системные ошибки
    1. Сравниваете CMS и фреймфорк. Да, битрикс это тоже фреймворк можно сказать. Но не голый, а на который уже поставили кучу всяких модулей. Вы же сравниваете голые красивые концепты и толстые готовые приложения.
    2. Сравниваете opensource и коммерческий продукт. Вся эта тема про композер больше опенсорсная. Именно там это все важно. Открытость, максимальная реиспользуемость и т.д.

    Ну и плюс все же какое-то преклонение перед «мировыми трендами» ощущается.

    Речь о том, что вы НЕ пытаетесь создавать решения, которые просто реиспользовать и развивать, и пытаетесь публиковать этот класс под видом как раз такого решения.

    Да. В этом вы правы. Я не пытаюсь создавать решения которые просто реиспользовать и развивать. Возможно займусь этим когда-нибудь. Однако я не пытаюсь этот класс распространить. Это просто пример, простенький класс который я приложил, чтобы не просто слова были, а более полное понимание по конкретной задаче.

    Инсталлятор для такого «центрального» модуля системы может обрастать довольно обширным функционалом.

    Вы мне будете рассказывать как использовать мой пример архитектуры? Серьезно? Речь не идет ни про какой центральный модуль. Этот модуль проекта что-то вроде набора функций в основном.
    Если у меня будет какая то отдельная задача, например формирование эксель файлов определенной структуры, то я сделаю отдельный модуль под эту задачу. Если будет следующая большая задача, то вынесу эту задачу в следующий модуль. Ничего тут не будет разрастаться. Про отдельные модули тоже есть в статье. Особенно прям поражает ваша уверенность, что я не знаю что такое инсталлятор и какой функционал там может быть.

    Я о том, что использование модуля в битриксе является избыточным в большинстве случаев, если на проекте используется composer

    Именно. В этом вся суть нашего спора. А если композера нет, то лучше все структурировать в модуле, а не просто файлами. Вы упрямо доказываете, что композер это панацея, я же так и не увидел модулей которые прям в каждый проект бы запихал. В битриксе настолько много готового функционала, что просто нечего ставить композером.

    Это какие из них условно полезные?

    Именно потому я говорю про условно полезные модули, они нужны не на каждом проекте. Сами по себе они может быть и крутые. PHPExcel я например довольно часто использую. Но все же не на каждом проекте.

    Про vendor — если заказчик удалит директорию vendor, то ее восстановление — дело одной команды в cli,

    А восстановление модуля дело одного клика мышкой. Только для одной команды cli программиста надо звать и поднимать его ночью, о чем вы так беспокоитесь, а восстановить модуль может и сам заказчик, как только увидит что отвалилось что-то.

    Я лично никак не могу понять, если у вас есть несколько проектов на Symfony, почему вы до сих пор так активно защищаете модули битрикса

    Защищаю в сравнении с композером? Ну да. На symfony вообще ничего нет. Там 100% придется использовать готовый код от других разработчиков. Именно поэтому для symfony использование композера несомненно оправдано. Там по другому никак. И композер это очень крутая штука для symfony. В битриксе же наоборот «вообще все» есть. Понятно что это преувеличение, но для запуска хорошего интернет магазина, например, ни одного модуля из композер не понадобится. И все будет работь отлично.

  • > Есть ощущение, что вы статью не читали. Посмотрели по диагонали, возмутились что нет композера и решили возмущение выразить. Серьезно. Слишком много снисхождения
    Не стоит все мои комментарии подгонять под одну гребенку. Статью я вашу прочитал. А насчет композера — конечно возмутился, ведь с помощью него вы смогли бы решить многие из тех вопросов, которые вы описали в статье, а также заодно решить ряд проблем, о которых вы даже не задумывались доселе.

    > Есть какая то грань до которой я готов разжовывать информацию. Так можно дойти до объяснений по открывающим тэгам php. У кого то может много времени уйти, прежде чем он поймет, что php код работает только внутри определенных тэгов. Будем это тоже пояснять?
    Я совсем не об этом. Бывают такие моменты, что люди «залипают» на каких-то глупых мелочах. А залипают они из-за неочевидных поступков других людей, которые не потрудились сделать «удобно». Пояснять, как работает php код, конечно же, никому не нужно, это крайности, и статья совсем не об этом.

    > Это уже не баг, а изменение ядра. Изначально речь шла, что вы помогаете сотрудникам битрикса с исправлением багов.
    А правка бага в ядре не является изменением поведения ядра чтоли? 🙂 Да, я постоянно натыкаюсь на баги в ядре. Да, я их исправляю в своей копии ядра и репортирую о проблеме в битрикс, чтобы они тоже поправили этот баг. Бизнес моих заказчиков не может ждать, пока битрикс будет годами выпускать заплатки на тот или иной свой функционал, так уж сложилось. Поэтому приходится выкручиваться. Так что да — правим баги в ядре и одновременно помогаем битриксу исправлять свои косяки «за бесплатно» (аттракцион невиданной щедрости прям)

    > Вы тут никакого противоречия не видите? Понятно что правильного варианта «вообще» нет. Безусловно я рассказываю правильный опыт разработки с моей точки зрения. Я рассказываю неправильно, но правильного и нет. Супер Мне нравится логика.
    Нет тут никаких противоречий. Еще раз. Вы говорите о «правильном» подходе с вашей точки зрения, когда даже у разработчиков ядра 1С Битрикс нет единого, «правильного» подхода к разработке своих модулей. Вы же заявляете о том, что разработали «правильную» схему построения всего проекта в целом. Супер, чо. А Мавроди когда-то всем тоже говорил, что вкладывать в его МММ — это «правильно».
    Я бы ничего на эту тему не написал, если бы слово «правильно» было заменено на «удобно». В прочем, ладно. Правильно, так правильно. Как говорит одна народная мудрость — «у каждого своя правда».

    >Ну молодцы конечно, оптимизировали немного, но где здесь 100-300кб о которых вы говорите? Этот пример как раз больше к моей точке зрения подходит. Большая часть скриптов используется вообще на всех страницах, и на некоторых подключены свои специфичные скрипты.
    Вы просили пример страницы, которая загружает 100-300кб после gzip. Я вам его дал. И этот пример отлично иллюстрирует всю проблематику. Согласно исследованиям умных людей, решающим фактором является первый хит посетителя. Если на первом хите сайт будет отзываться очень долго, то велика вероятность, что посетитель покинет ваш сайт, не дождавшись окончания загрузки.
    А теперь попробуйте зайти с пустым кешем в карточку товара со смартфона, у которого в качестве интернета «типичный региональный 3G», и вам придется подождать секунд 20-30 прежде, чем вы сможете хоть как-то взаимодействовать с сайтом. Это и есть проблема. А вы преподносите эту проблему как хорошую практику.
    Даже битрикс, который вам так сильно нравится, пытается делить статику по страницам, чтобы не грузить лишнего. Да, он это делает плохо, но он это делает. Если уж мое мнение вам не интересно, то посмотрите хотя бы на мнение высокоуважаемого битрикса.

    > Сайт написан на ангуляре. Там не столько скрипты, сколько контент подгружается. Тот кто пишет на ангуляре я думаю понимает что именно он делает и где какие скрипты подключать.
    Если говорить о фронте — то да, там ангуляр
    Если говорить о бекенде — то там Yii и Битрикс.
    Но в общем-то какое значение это имеет, когда при первом хите ваш сайт грузится 20-30, а то и все 60 секунд, сжирая тонны трафика. 90-99% времени загрузки в таких случаях — это время на загрузку и обработку статики, и это самое узкое место в вебе на сегодняшний момент. И его нужно оптимизировать, хотите вы этого или нет, когда речь заходит о серьезных проектах.

    > И вы похоже опять не видите разницу между общим объемом скриптов, и объемом скриптов нужным для конкретной страницы.
    Я намеренно эту разницу игнорирую, потому-что посетителю абсолютно все равно, как у вас склеены скрипты и стили. Посетитель хочет видеть быстрый отклик от сайта, и это имеет решающее значение.

    > Нет никакого общего тренда. Везде все делается по разному.
    Тема была про тренды в мире битрикса. Если вы не слышали о таких трендах, то не стоит говорить об их отсутствии. На просторах рунета уже довольно давно существует сообщество разработчиков под 1С Битрикс, которые вырабатывают эти общие практики и делятся ими. В этом сообществе присутствуют люди с огромным стажем работы и широчайшим кругозором

    > Вы на мой взгляд совершаете две системные ошибки
    > 1. Сравниваете CMS и фреймфорк. Да, битрикс это тоже фреймворк можно сказать. Но не голый, а на который уже поставили кучу всяких модулей. Вы же сравниваете голые красивые концепты и толстые готовые приложения.
    Назвать битрикс «толстым» конечно можно. А вот «готовым» приложением — увы, язык не поворачивается. Приложение является готовым, когда его можно безболезненно развивать, а вот в битриксе нет ни одного нормального, продуманного до конца, и реализованного до конца решения, которое можно было бы безболезненно расширять сторонним разработчикам. Есть только попытки сделать это. Тогда как в мире фреймворков такой проблемы в общем-то не стоит. Примеров могу привести вагон и маленькую тележку, но это все равно выходит за рамки статьи и нашего спора.
    Сравнивать битрикс и фреймворки, на мой взгляд, вполне корректно, потому что битрикс подается как «модульный фреймворк» и как «CMS/CMF». Битрикс несостоятелен как модульный фреймворк, т.к. модуль в понятии битрикса считается таким «нечто», которое практически не подвержено влиянию извне (в 99% случаев за исключением событий), тогда как любой другой современный модульный фреймворк предоставляет очень широкий спектр возможностей по расширению функционала модулей.
    Сравнивать framework и CMS/CMF, конечно, не имеет смысла, чем я и не пытаюсь заниматься. Хотя можно попробовать сравнить Symfony CMF с битриксовой CMS, и разница будет «налицо».

    > 2. Сравниваете opensource и коммерческий продукт. Вся эта тема про композер больше опенсорсная.
    То, что композер опенсорсный, не говорит о том, что его нет смысла применять в битриксе.
    К тому же битрикс — это тоже продукт с открытым исходным кодом, разве что лицензирование более жесткое и имеет финансовую подоплеку.

    > Именно там это все важно. Открытость, максимальная реиспользуемость и т.д.
    Битрикс сам поставил открытость своих продуктов во главу угла еще в 9й версии, так что это важно.
    Реиспользуемость … ну я прям даже не знаю. Неужели вам не нужна на ваших проектах реиспользуемость ваших же модулей, компонентов? Сами же пишете в своих комментах, что таскаете за собой всякий функционал от проекта к проекту. Так зачем это делать руками, когда это все уже давно автоматизировано? Не вижу смысла

    > Вы мне будете рассказывать как использовать мой пример архитектуры? Серьезно? Речь не идет ни про какой центральный модуль. Этот модуль проекта что-то вроде набора функций в основном.
    Ок, я понял. У вас модули — это наборы функций. Классы у вас, судя по всему, тоже — наборы функций. Понятно, вопросов не имею

    > Вы упрямо доказываете, что композер это панацея
    Именно панацея. Избавляет от очень большого количества головной боли.

    > я же так и не увидел модулей которые прям в каждый проект бы запихал.
    > В битриксе настолько много готового функционала, что просто нечего ставить композером.
    Значит вы просто не сталкивались с задачами, которые требуют наличия кода, которого в битриксе нет.
    Отправка письма по любому трансферу, не поддерживаемому битриксом? Подключаем либу через композер
    Асинхронная обработка задач сервером очередей? Подключаем либу через композер
    Профилирование своего кода на prod-окружении? Ставим либу через композер
    Генерация pdf, xlsx, docx, шаблонизация, тестирование, миграции, логирование, организация API, СLI интерфейса, геолокация, работа со словарями и сотни других задач … все это было уже решено давным давно и выложено в опенсорс. И нет никакого смысла этим не пользоваться. Сейчас даже нативные клиенты для API различных сервисов распространяются через composer, что избавляет от головной боли, связанной с обновлением.
    А те задачи, которые в битриксе якобы решены (работа с файлами, HTTP протоколом, например) на самом деле решены не в достаточной степени, и с помощью composer можно подключить библиотеки, которые покроют все ваши потребности в этом плане, чего никогда не сделает битрикс.
    В общем — да, я считаю composer панацеей в некотором роде.
    А то, что предлагает битрикс из коробки далеко не всегда можно использовать. Для начальных нужд этого может быть и хватит, но вот для серьезных проектов — вряд ли.

    > Именно потому я говорю про условно полезные модули, они нужны не на каждом проекте. Сами по себе они может быть и крутые. PHPExcel я например довольно часто использую. Но все же не на каждом проекте.
    Я не понимаю. Вы хотите использовать composer только в том случае, если у вас появится несколько модулей, которые нужно раскинуть по всем проектам? composer не для этого был разработан

    > А восстановление модуля дело одного клика мышкой.
    Опять же — все зависит от инсталлятора/деинсталлятора. Веб-интерфейс — штука довольно ненадежная. Одна малейшая ошибка, и все может отвалиться. Одна маленькая зависимость в init.php от вашего неустановленного модуля, и все, никто не доберется до формы установки без программиста

    > Только для одной команды cli программиста надо звать и поднимать его ночью, о чем вы так беспокоитесь, а восстановить модуль может и сам заказчик, как только увидит что отвалилось что-то.
    Очень редко приходилось видеть заказчиков, которые в случае падения сайта НЕ поднимают ночью программистов. Вы — везунчик 🙂

    > Понятно что это преувеличение, но для запуска хорошего интернет магазина, например, ни одного модуля из композер не понадобится. И все будет работь отлично.
    Да, битрикс — замечательная платформа, которая позволяет в пару кликов развернуть типовой магазин. Но вот ценность такого магазина сводится к нулю, когда приходится его развивать. Даже малейшие правки контента будут приводить к нарушению огромного количества таких фундаментальных правил, как KISS, DRY и SOLID, что через полгода поддержки приведет к тому, что все это нужно будет выкинуть и создать новый сайт с нуля (и хорошо бы — со сменой технологической платформы). Битрикс никак не стимулирует создавать качественные решения, не следует современным трендам, гнет свою линию. А линия эта — перечеркивает все надежды на комфортное сопровождение вашего и чужого кода в ближайшем будущем при использовании этой технологической платформы

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

  • Отлично. Я теперь еще и Мавроди. Что еще приятного скажете?

    Ок, я понял. У вас модули — это наборы функций. Классы у вас, судя по всему, тоже — наборы функций. Понятно, вопросов не имею

    Конечно. Только илита может в ООП 🙂 Блок про модули в статье выше можно игнорировать. Про то что только избранные знают как работают инсталлеры в модуле я уже понял, теперь и про ООП буду знать 🙂

    Вы просили пример страницы, которая загружает 100-300кб после gzip. Я вам его дал.

    Еще раз кратко историю диалога.
    1. В статье написано что можно и вообще все скрипты и стили объединить в шаблоне, но если есть страница, где много скриптов именно для этой страницы, то разумно их вынести отдельно
    2. Вы говорите, что вообще все делить надо по страницам. И там экономия будет 100-300кб.
    3. Я говорю приведите пример страницы, которая именно специфичных для нее скриптов грузит 100-300кб. Без учета общих скриптов всего сайта. Перечитал комментарий предыдущий, возможно неясно написал, но спрашивал именно про это. Я думал в контексте диалога это будет понятно.
    4. Вы привели в качестве примеров мвидео, где на отдельную страницу +10кб скриптов грузится и mos.ru, где хоть отдельные страницы и подгружают много скриптов, но по факту это не скрипты, а контент.

    Я вижу, как дискуссия заходит в тупик.

    Определенно.

  • Павел:

    Отличная статья, первые комменты тоже по делу, дальше холивар.

    Пока не осилил ваш tools.events, и использую локальный модуль для подключения обработчиков событий

  • На мой взгляд, для начинающих — эта статья более, чем годная.
    А статьи Максима рассчитаны на более зрелых разработчиков, которым нужна пища для размышления на тему «я уже все знаю, все могу — что еще я могу улучшить в своем рабочем процессе, организации кода и тд».

    Да и когда плотно работаешь с чем-то кроме битрикса — все по другому воспринимаешь. В битриксе все кажется неправильным. Это нормально 🙂

    Главное помнить, что амбиции разработчика «я все делаю, как в лучших практиках» должны быть пропорциональны задачам, которые ставит бизнес. Битрикс в первую очередь решает задачи бизнеса «здесь и сейчас».

  • Nikolays93:

    Будьте аккуратнее с PATH_TO!!

    В общем, заигрался с PATH_TO и поставил define(‘PATH_TO__CATALOG’, ‘/catalog/’); добавил константу в настройку компонента bitrix:catalog и получил не работающий каталог.

    Смотрю изменения git и вижу в urlrewrite.php:
    «`
    array(
    «CONDITION» => «#^={PATH_TO__CATALOG}#»,
    «RULE» => «»,
    «ID» => «bitrix:catalog»,
    «PATH» => «/catalog/index.php»,
    ),
    `
    Такой подход в CONDITION очевидно не работает. Подумал что такой подход будет удобен в начальных стадиях разработки. Есть ли смысл с этим бороться?

Добавить комментарий для Михаил Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *