← Назад в блог

Папка /local в 1C-Битрикс: структура проекта без боли и костылей

Практический разбор папки /local в 1C-Битрикс: правильная структура php_interface, init.php, components, templates и modules по документации. Как не ломать обновления ядра и упростить поддержку.

Папка /local в 1C-Битрикс: структура проекта без боли и костылей

Требования

  • Опыт разработки под 1C-Битрикс
  • Понимание структуры проекта и php_interface
  • Поддержка или доработка существующего сайта

Папка /local в 1C-Битрикс: как разложить проект по полочкам и не страдать при доработках

Открывал чужой init.php и видел там сотни строк хелперов, SQL и обработчиков вперемешку — знакомо. Разобраться, где что лежит и что можно трогать при обновлении ядра, бывает муторно. Ниже — только практика по папке /local: как в документации Bitrix и как лучше организовать код, чтобы обновления не ломали кастом.

Разберём структуру по шагам, с путями и примерами кода.

Архитектурная идея: ядро и пользовательский код


Зачем вообще нужна /local

В документации Bitrix чётко разделяют:

  • /bitrix — ядро продукта, его не правим.
  • /local — весь наш код: компоненты, шаблоны, обработчики, свои модули.

При обновлении продукта каталог /bitrix перезаписывается. Всё, что лежит там «для удобства», однажды может быть затерто или сломано. Всё кастомное имеет смысл держать в /local: он обновлениями не затрагивается.

Кратко: не трогаем /bitrix — работаем в /local.


Базовая структура /local: как в документации и как в жизни

Минимально система ожидает под /local хотя бы точку входа в свой PHP:

/local
├── php_interface
│   ├── init.php
│   └── dbconn.php   // опционально, если выносим настройки подключения к БД

Файл /local/php_interface/init.php подключается на каждом запросе — это единая точка входа в пользовательский PHP. От того, как он устроен, зависит, превратится ли проект в поддерживаемый или в «свалку».

Структура /local: php_interface, components, templates


/local/php_interface: как не превратить init.php в свалку

❌ Плохо (типичный legacy)

В одном файле — и обработчики, и хелперы, и куски логики:

<?php
// init.php — тысячи строк
AddEventHandler('main', 'OnProlog', function() { ... });
AddEventHandler('sale', 'OnOrderSave', 'myOrderHandler');

function formatPrice($price) { return number_format($price, 0, '', ' '); }
function getCatalogIblockId() { return 12; }
// ещё десятки функций и SQL-запросы...

Такой файл тяжело читать, тестировать и безопасно менять при обновлениях.

Анти-паттерн init.php: свалка кода vs загрузчик

✅ Правильно: init.php только подключает файлы

По рекомендациям Bitrix, в init.php имеет смысл оставить только подключение отдельных файлов. Вся логика — в классах и отдельных модулях.

Рекомендуемая структура

/local/php_interface
├── init.php
├── events.php      // регистрация обработчиков событий
├── constants.php   // константы проекта
├── autoload.php    // автозагрузка классов из /local/php_interface/lib
└── lib/
    ├── Helpers/
    ├── Services/
    └── Repositories/

Пример init.php

<?php
// /local/php_interface/init.php

require_once __DIR__ . '/constants.php';
require_once __DIR__ . '/autoload.php';
require_once __DIR__ . '/events.php';

Коротко и предсказуемо: при доработках правим отдельные файлы, а не гигантский init.php.


constants.php — константы в одном месте

Вынос ID инфоблоков, флагов окружения и прочего в константы избавляет от «магических чисел» по коду:

<?php
// /local/php_interface/constants.php

define('PROJECT_ENV', 'production');
define('CATALOG_IBLOCK_ID', 12);
define('NEWS_IBLOCK_ID', 3);
define('PARTNERS_IBLOCK_ID', 8);

В компонентах и сервисах используем CATALOG_IBLOCK_ID, а не голую двенадцать — так проще искать и менять при переносе на другой сайт.


autoload.php — автозагрузка своего кода

Bitrix поддерживает регистрацию автозагрузки классов из /local/php_interface/lib через Loader::registerAutoLoadClasses. Это не Composer, но стабильно работает в любой типовой установке.

Пример регистрации сервиса и хелпера:

<?php
// /local/php_interface/autoload.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',
]);

Пример самого класса (логика не в init.php, а в сервисе):

<?php
// /local/php_interface/lib/Services/OrderService.php

namespace Project\Services;

use Bitrix\Main\Loader;

class OrderService
{
    public static function onOrderSaved(\Bitrix\Main\Event $event): void
    {
        $order = $event->getParameter('ENTITY');
        if (!$order) {
            return;
        }
        // Отправка в CRM, обновление склада и т.д.
        // Всё здесь, а не в events.php
    }
}

events.php — только регистрация событий

В этом файле — исключительно привязка событий к классам или функциям. Бизнес-логика остаётся в классах.

<?php
// /local/php_interface/events.php

use Bitrix\Main\EventManager;

$eventManager = EventManager::getInstance();

$eventManager->addEventHandler(
    'sale',
    'OnSaleOrderSaved',
    ['Project\\Services\\OrderService', 'onOrderSaved']
);

$eventManager->addEventHandler(
    'iblock',
    'OnAfterIBlockElementAdd',
    ['Project\\Services\\CatalogService', 'onElementAdd']
);

Так проще искать обработчик по имени модуля и события и не размазывать логику по init.php.


/local/components: свои компоненты без боли

Компоненты система ищет сначала в /local/components, затем в /bitrix/components. Свои и доработанные компоненты логично держать в /local:

/local/components/ваш_неймспейс/имя.компонента/

Пример: кастомный вывод раздела каталога:

/local/components/my/catalog.section.custom/
├── component.php
├── .description.php
├── templates/
│   └── .default/
│       ├── template.php
│       └── result_modifier.php

Миграция с legacy-проекта

Если компонент до сих пор лежит в /bitrix/components:

  1. Копируем папку целиком в /local/components (тот же неймспейс и имя).
  2. Проверяем работу сайта (кеш при необходимости сбрасываем).
  3. Только после этого удаляем копию из /bitrix/components.

Шаблоны компонентов тоже лучше хранить в /local/templates, а не править штатные в /bitrix/templates.


/local/templates: свои шаблоны сайта

Типовая структура:

/local/templates
├── main/
│   ├── header.php
│   ├── footer.php
│   ├── description.php
│   └── components/

Всё, что правим в шаблоне сайта, делаем в копии под /local/templates. Правки в /bitrix/templates при обновлении могут быть перезаписаны.


/local/modules: когда проект дорос

Если появляется своя логика (общие сервисы, интеграции, сложная бизнес-логика), удобно вынести её в отдельный модуль под /local/modules:

/local/modules/project.core/
├── install/
│   └── index.php
├── lib/
│   └── SomeService.php
└── include.php

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


/local/tools: скрипты и утилиты

В /local/tools обычно кладут разовые или фоновые скрипты: импорт, синхронизация, выгрузки. Не API и не основная бизнес-логика — именно утилиты.

/local/tools
├── import.php
├── sync_catalog.php

Вызов — по необходимости (cron, ручной запуск), без смешивания с основным кодом сайта.


Миграция с legacy: как не уронить прод

  1. Компоненты: копируем из /bitrix/components в /local/components, проверяем, затем удаляем из /bitrix.
  2. init.php: сначала выносим функции в отдельные файлы и подключаем через require_once, затем по мере возможности переносим логику в классы и подключаем через autoload.php и events.php. Рефакторим по шагам, а не «всё сразу».

Так снижаем риск поломки продакшена при наведении порядка.


Чек-лист здорового /local

Имеет смысл стремиться к тому, чтобы:

  • В init.php было не больше 10–20 строк (только подключения).
  • Регистрация событий — в events.php.
  • Бизнес-логика — в классах под /local/php_interface/lib или в своём модуле.
  • Свои компоненты — только в /local/components.
  • Шаблоны — только в /local/templates.
  • В /bitrix ничего не правим.

Типичные анти-паттерны (и как исправить)

ПроблемаЧто сделать
Всё в init.phpВынести в lib/, подключить через autoload.php и events.php.
Компоненты в /bitrix/componentsПеренести в /local/components и проверить работу.
Правки шаблонов в /bitrix/templatesСделать копию в /local/templates и править её.

Мини-кейс из практики

Реальный проект на 1C-Битрикс, сайт жил уже несколько лет. В /local/php_interface/init.php накопилось под две тысячи строк: десятки AddEventHandler (каталог, заказы, инфоблоки), функции-хелперы для цен и вывода элементов, куски CIBlockElement::GetList и опросов к БД — всё в одном файле. При обновлении ядра страшно было трогать что угодно; новый разработчик тратил недели, чтобы найти, где вешается обработчик и куда дописать логику. Сделали по рекомендациям из документации: вынесли константы в constants.php, регистрацию событий — в events.php, классы — в /local/php_interface/lib с автозагрузкой через Loader::registerAutoLoadClasses. Кастомные компоненты перенесли из /bitrix/components в /local/components. В итоге init.php — около десятка строк подключений, логика в сервисах и обработчиках. Онбординг новых людей и доработки по заявкам заметно ускорились, обновления продукта перестали вызывать панику.


Итог

Папка /local в 1C-Битрикс — не формальность, а способ держать кастомный код отдельно от ядра и спокойно обновляться. Стоит воспринимать её как основное место для своего кода: проектировать структуру осознанно, не превращая init.php в свалку и не размазывая правки по /bitrix.

/bitrix не трогаем — всё своё ведём в /local.


Связанные сниппеты

0 просмотров

Комментарии

Загрузка комментариев...
Пока нет комментариев. Будьте первым!