DEV Community

Андрей Викулов (VProger)
Андрей Викулов (VProger)

Posted on • Originally published at viku-lov.ru on

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

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

Папка /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 // опционально, если выносим настройки подключения к БД

Enter fullscreen mode Exit fullscreen mode

Файл /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-запросы...

Enter fullscreen mode Exit fullscreen mode

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

!Анти-паттерн 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/

Enter fullscreen mode Exit fullscreen mode

Пример init.php


<?php

// /local/php\_interface/init.php

require\_once \_\_DIR\_\_ . '/constants.php';

require\_once \_\_DIR\_\_ . '/autoload.php';

require\_once \_\_DIR\_\_ . '/events.php';

Enter fullscreen mode Exit fullscreen mode

Коротко и предсказуемо: при доработках правим отдельные файлы, а не гигантский 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);

Enter fullscreen mode Exit fullscreen mode

В компонентах и сервисах используем 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',

]);

Enter fullscreen mode Exit fullscreen mode

Пример самого класса (логика не в 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

}

}

Enter fullscreen mode Exit fullscreen mode

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']

);

Enter fullscreen mode Exit fullscreen mode

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


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

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


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

Enter fullscreen mode Exit fullscreen mode

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


/local/components/my/catalog.section.custom/

├── component.php

├── .description.php

├── templates/

│ └── .default/

│ ├── template.php

│ └── result\_modifier.php

Enter fullscreen mode Exit fullscreen mode

Миграция с 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/

Enter fullscreen mode Exit fullscreen mode

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


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

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


/local/modules/project.core/

├── install/

│ └── index.php

├── lib/

│ └── SomeService.php

└── include.php

Enter fullscreen mode Exit fullscreen mode

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


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

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


/local/tools

├── import.php

├── sync\_catalog.php

Enter fullscreen mode Exit fullscreen mode

Вызов — по необходимости (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.


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

  • Bitrix /local: init.php — только подключение файлов
  • Bitrix /local: constants.php — константы проекта
  • Bitrix /local: autoload.php — автозагрузка классов из lib
  • Bitrix /local: events.php — регистрация обработчиков событий

Read more on viku-lov.ru

Top comments (0)