Папка /local в 1C-Битрикс: структура проекта без боли и костылей
После обновления ядра Битрикс кастомный код пропадает или ломается. Как правильно организовать /local: php_interface, init.php, components, templates — чтобы update и composer не затирали правки. Код и типичные конфликты.
Требования
- Опыт разработки под 1C-Битрикс
- Понимание структуры проекта и php_interface
- Поддержка или доработка существующего сайта
Папка /local в 1C-Битрикс: структура проекта без боли и костылей
Запрос bitrix local папка структура или после обновления битрикс пропал кастом упирается в одну задачу: кастомный код размазан по /bitrix или по одному гигантскому init.php, и при обновлении ядра правки затираются или перестают работать. Проблема: как организовать /local, чтобы обновления продукта и при необходимости Composer не ломали ваш код. Ниже — конкретная структура каталогов, пути к файлам, минимум три блока кода, проверка и типичные ошибки. Для автоматизации и агентов на той же платформе пригодится Backend-автоматизация: cron, агенты Bitrix.

В чём проблема
Симптомы:
- После обновления 1C-Битрикс пропадают правки в компонентах или шаблонах — вы правили файлы в
/bitrix/componentsили/bitrix/templates, ядро их перезаписало. - В
init.phpсотни строк: обработчики событий, хелперы, SQL — невозможно быстро найти, где вешается обработчик и что можно безопасно менять. - Composer или скрипты обновления затирают кастомные файлы, потому что они лежат не в
/local. - Новый разработчик тратит дни, чтобы понять, где регистрируются события и куда дописывать логику.
Почему возникает:
В документации Bitrix чётко разделено: /bitrix — ядро, при обновлении перезаписывается; /local — весь кастомный код. Если компоненты, шаблоны или логика лежат в /bitrix или свалены в один init.php, обновление продукта и типовые скрипты приводят к потере правок и конфликтам. Отсутствие явной структуры в /local (один файл вместо events.php, autoload.php, lib/) усложняет поддержку и повышает риск поломки при деплое или update.
Как быстро проверить, что кастом в зоне риска: если при обновлении продукта через стандартную процедуру вы хотя бы раз теряли правки в компонентах или в init.php — кастом уже в неправильном месте. Если новый разработчик не может за 15 минут найти, где подключается обработчик заказа или где лежат константы инфоблоков — структуру стоит привести к описанной ниже.
Рабочее решение
Стек: 1C-Битрикс (актуальная редакция), PHP 7.4+. Среда: prod, BitrixVM, Docker — без изменений в ядре /bitrix.
Целевая структура /local
/local
├── php_interface
│ ├── init.php
│ ├── constants.php
│ ├── autoload.php
│ ├── events.php
│ └── lib/
│ ├── Helpers/
│ └── Services/
├── components/
├── templates/
├── modules/
└── tools/
Ядро подключает только /local/php_interface/init.php. Всё остальное подключается из него — так обновление /bitrix не затрагивает ваш код.
1) init.php — только подключение файлов
Файл: /local/php_interface/init.php
<?php
require_once __DIR__ . '/constants.php';
require_once __DIR__ . '/autoload.php';
require_once __DIR__ . '/events.php';
В этом файле не должно быть логики, только require_once. Так вы не превращаете точку входа в свалку и не ломаете порядок подключений при обновлении.
2) constants.php — константы проекта
Файл: /local/php_interface/constants.php
<?php
define('PROJECT_ENV', 'production');
define('CATALOG_IBLOCK_ID', 12);
define('NEWS_IBLOCK_ID', 3);
ID инфоблоков и флаги окружения в одном месте — проще менять при переносе и не искать «магические числа» по коду.
3) autoload.php — автозагрузка классов из /local
Файл: /local/php_interface/autoload.php
<?php
use Bitrix\Main\Loader;
Loader::registerAutoLoadClasses(null, [
'Project\\Services\\OrderService' =>
'/local/php_interface/lib/Services/OrderService.php',
'Project\\Helpers\\Catalog' =>
'/local/php_interface/lib/Helpers/Catalog.php',
]);
Классы лежат в /local/php_interface/lib/, логика не в init.php. Пример сервиса:
Файл: /local/php_interface/lib/Services/OrderService.php
<?php
namespace Project\Services;
class OrderService
{
public static function onOrderSaved(\Bitrix\Main\Event $event): void
{
$order = $event->getParameter('ENTITY');
if (!$order) {
return;
}
// Интеграция с CRM, склад и т.д. — здесь, а не в events.php
}
}
4) events.php — только регистрация обработчиков
Файл: /local/php_interface/events.php
<?php
use Bitrix\Main\EventManager;
$eventManager = EventManager::getInstance();
$eventManager->addEventHandler(
'sale',
'OnSaleOrderSaved',
['Project\\Services\\OrderService', 'onOrderSaved']
);
$eventManager->addEventHandler(
'iblock',
'OnAfterIBlockElementAdd',
['Project\\Services\\CatalogService', 'onElementAdd']
);
Бизнес-логика — в классах в lib/, в events.php только привязка событий к методам. Так проще искать обработчик по модулю и событию.
5) Компоненты и шаблоны только в /local
Свои и доработанные компоненты размещайте в /local/components/ваш_неймспейс/имя.компонента/. Система сначала ищет компонент в /local/components, затем в /bitrix/components. Шаблоны сайта — в /local/templates/. Правки в /bitrix/templates и /bitrix/components при обновлении ядра могут быть перезаписаны.
Пример структуры своего компонента:
/local/components/my/catalog.section.custom/
├── component.php
├── .description.php
├── templates/
│ └── .default/
│ ├── template.php
│ └── result_modifier.php
Миграция с legacy: скопировать компонент из /bitrix/components в /local/components с тем же путём, проверить работу сайта, затем удалить копию из /bitrix/components.
Почему не оставлять логику в init.php: при обновлении ядра и при деплое один большой файл сложнее мержить и откатывать. Если константы, события и классы разнесены по файлам, можно быстро найти нужный обработчик по имени модуля и события в events.php, а бизнес-логику править в одном классе в lib/. Это снижает риск случайно сломать чужой обработчик при добавлении своего.
Проверка результата
1. Компонент подхватывается из /local
Подключите компонент на любой странице (например, ваш кастомный из my:catalog.section.custom). Убедитесь, что используется файл из /local/components, а не из /bitrix: временно добавьте в component.php строку с уникальным комментарием и проверьте вывод или проверьте путь в отладчике.
2. События срабатывают
В OrderService::onOrderSaved добавьте временно запись в лог или отправку в мониторинг. Создайте тестовый заказ — в логе должна появиться запись. После проверки уберите отладочный код.
3. После обновления ядра кастом на месте
Выполните обновление продукта по инструкции Bitrix. Проверьте, что в /local/php_interface/init.php по-прежнему только три строки require_once, а компоненты и шаблоны остаются в /local и работают.
Ожидаемый результат: обновление не затирает ваши файлы, структура предсказуема, обработчики и классы легко найти по путям выше.
Типичные ошибки
1. Всё в одном init.php — обработчики, хелперы и SQL в одном файле. При обновлении и доработках высок риск конфликтов и трудно понять порядок выполнения. Вынесите константы в constants.php, регистрацию событий в events.php, классы в lib/ с подключением через autoload.php; в init.php оставьте только три require_once.
2. Компоненты и шаблоны в /bitrix — при обновлении ядра правки затираются. Перенесите все кастомные компоненты в /local/components, шаблоны — в /local/templates. Проверьте работу, затем удалите копии из /bitrix.
3. Правки в ядре (/bitrix) — любой файл в /bitrix может быть перезаписан при update. Весь кастом должен находиться в /local; при необходимости переопределяйте только через события и свои компоненты/шаблоны в /local.
4. Composer и /local — если используете Composer, подключайте автозагрузку из vendor в init.php после или до autoload.php и не кладите кастомные классы проекта в vendor. Собственный код — в /local/php_interface/lib/ с регистрацией через Loader::registerAutoLoadClasses, как в блоке выше.
Если после переноса что-то перестало работать: проверьте, что пути в Loader::registerAutoLoadClasses ведут на реальные файлы (с учётом регистра символов на Linux). Убедитесь, что в events.php имена классов и методов указаны с двойным обратным слэшем (Project\\Services\\OrderService). После переноса компонента из /bitrix/components в /local/components очистите кеш Bitrix (Настройки → Производительность) и проверьте вызов компонента в шаблоне — путь к компоненту (неймспейс и имя) не меняется, меняется только физическое расположение файлов. При необходимости собственный модуль под /local/modules даёт автозагрузку через ядро и изоляцию по namespace — подходит, когда проект растёт и общих сервисов становится много. Резюме: одна проблема — после обновления ядра кастом пропадает или структура нечитаема; решение — вся логика в /local, init.php только подключает constants.php, autoload.php, events.php, компоненты и шаблоны только в /local; проверка — компонент из /local вызывается, события срабатывают, после update файлы на месте; типичные ошибки — свалка в init.php, правки в /bitrix, компоненты не в /local, путаница Composer и своего кода. Скрипты и утилиты (импорт, выгрузки, cron) удобно держать в /local/tools и вызывать по необходимости, не смешивая с основным кодом сайта. Структура с отдельными файлами для констант, автозагрузки и событий упрощает онбординг новых разработчиков и снижает риск конфликтов при совместной работе в Git. Перед большим рефакторингом сделайте резервную копию /local и базы.
Где применять
- Prod — основная среда: структура
/localи отказ от правок в/bitrixснижают риск поломки при обновлении продукта. - Docker — тот же принцип: образ собирается с ядром в
/bitrix, кастом монтируется или копируется в/local. - BitrixVM — обновления через панель не должны затирать
/local; убедитесь, что скрипты обновления не перезаписываютphp_interface,componentsиtemplatesв/local. - CI/CD — деплой должен класть только файлы в
/local(и при необходимостиvendor), не трогая содержимое/bitrixпосле установки/обновления ядра.
Сниппеты по теме: Bitrix /local: init.php — только подключение файлов, constants.php, autoload.php, events.php. Дополнительно: двусторонняя синхронизация статусов CMS ↔ CRM в Bitrix.



Комментарии