Последние записи
Хостинг для сайта
Если выбираете хостинг под проект — советую Timeweb. Современная инфраструктура, широкий выбор тарифов от стартовых до VPS под нагрузку, отзывчивая техподдержка, которая отвечает по существу, а не отписками. Я сам держу на нём часть своих проектов и рекомендую клиентам.
Перейти Партнёрская ссылка. Для вас цена не меняется.Современная разработка на Битрикс: обзор технологий, инфраструктуры и практик
Актуально на 2026 год. Материал проверялся для 1С-Битрикс: Управление сайтом (актуальные релизы), PHP 8.2/8.3, MySQL 8.0 / Percona Server 8.0. Перед применением сверяйтесь с официальной документацией вендора: поддержка версий PHP и модулей зависит от релиза ядра.
Почему это обзор, а не инженерный гид
Изначально этот материал задумывался как инженерно-методический разбор современной разработки на Битрикс: с полными примерами, разбором ошибок и пошаговыми инструкциями. Но чем дальше я заходил, тем очевиднее становилось, что тема не помещается в одну статью. Когда количество подтем перевалило за двадцать, объём черновика перевалил за пятнадцать тысяч строк, а каждая тема при этом была в лучшем случае не раскрыта — стало понятно, что такой формат не работает. Раскрывать каждую тему по-настоящему — это отдельные статьи, а не одна.
Поэтому концепция поменялась. Перед вами — обзор технологий для разработки сайтов на Битрикс. Что применять, когда это нужно и как использовать. По каждой теме — сжато, по делу, с примерами и с разбором плюсов и минусов, чтобы было понятно, стоит ли вообще браться за эту технологию в конкретном проекте. Углублять или нет — решайте сами.
Материал ориентирован на команды, которые занимаются созданием сайтов на 1С-Битрикс — от небольших студий до enterprise-разработки. Всё, что здесь описано, применяется при развёртывании Битрикс-проектов в промышленном режиме и при развитии уже существующих интернет-магазинов на Битрикс.
Важно: примеры кода в статье — учебные и упрощённые. Они показывают подход, а не готовое продакшен-решение. Перед использованием на боевом сервере адаптируйте их под проект и протестируйте на staging.
Часть 1. Инфраструктура и DevOps
Почему BitrixVM — чаще всего только для старта
BitrixVM — это готовый образ виртуальной машины с преднастроенным стеком: Nginx, PHP, MySQL, memcached, push&pull. Для быстрого развёртывания тестового сайта, обучения или пилотного проекта она удобна: поставил образ, запустил скрипт настройки, получил работающий Битрикс за полчаса.
Плюсы: быстрый старт, всё уже настроено, меньше шансов ошибиться на этапе развёртывания.
Минусы: тянет за собой пул пакетов, версии которых отстают от актуальных; обновления платформы могут сломать конфигурацию Nginx или PHP; нельзя гибко управлять версиями PHP для разных проектов на одном сервере.
Для продакшена обычно предпочтительнее чистый стек на Ubuntu или Debian с Nginx, PHP-FPM 8.2 или 8.3, Percona Server или MySQL 8.0. Версия PHP выбирается под конкретный проект: Bitrix стабильно работает на 8.2; 8.3 подходит для новых сайтов без legacy-модулей, но совместимость нужно проверять по матрице вендора.
Nginx-конфиг для Битрикс: ЧПУ, композит, статика, таймауты
Конфигурация Nginx для разработки на Битрикс имеет несколько обязательных мест. Первое — try_files с urlrewrite.php, иначе ЧПУ работать не будет. Второе — отдача композитного кэша напрямую из Nginx: если файл готового html существует, отдать его; иначе передать запрос в PHP-FPM. Третье — корректная обработка статики. Четвёртое — увеличенные таймауты fastcgi_read_timeout для тяжёлых операций. Пятое — директива client_max_body_size, которая по умолчанию в Nginx равна 1 МБ и режет загрузку файлов через админку и формы. Для интернет-магазина с загрузкой изображений и документов её нужно поднять минимум до 64 МБ, лучше — до 128 МБ, синхронизировав с upload_max_filesize и post_max_size в PHP.
Композитный кэш Bitrix хранится в виде готовых index.html по пути /bitrix/html_pages/<host><uri>/index.html. Именно этот путь и нужно проверять первым:
server {
listen 80;
server_name domain.ru;
root /var/www/domain.ru;
index index.php;
client_max_body_size 128M;
client_body_buffer_size 4M;
location / {
try_files /bitrix/html_pages/$host$uri/index.html $uri $uri/ /bitrix/urlrewrite.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 300;
fastcgi_send_timeout 300;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
expires 30d;
access_log off;
}
# Защита от прямого доступа к композитному кэшу
location ~ ^/bitrix/html_pages/ {
internal;
}
}
Без location ~ ^/bitrix/html_pages/ { internal; } композитные index.html открываются по прямой ссылке — это утечка контента и потенциальная проблема с индексацией. Без правильного пути $host$uri/index.html композит не отдаётся вообще, и весь смысл его включения теряется: нагрузка на PHP-FPM остаётся прежней.
Плюсы композитного кэша: снимает нагрузку с PHP-FPM в разы, страницы отдаются за миллисекунды. Минусы: не работает на динамических страницах с формами, корзиной, персональными данными — там композит приходится отключать. Для интернет-магазина на Битрикс с посещаемостью от 50 000 хостов в сутки композит — важный элемент, но применять его нужно точечно.
Docker и Docker Compose
Разворачивать Битрикс-проект вручную на каждом сервере — трудозатратно и чревато расхождениями между окружениями. Docker и Docker Compose дают воспроизводимость: одинаковый стек на локальной машине, на staging и на production. Для Bitrix есть готовые образы, но лучше собирать свой на базе php:8.2-fpm с нужными расширениями.
version: '3.8'
services:
app:
build: ./docker/php
volumes:
- ./:/var/www/html
depends_on:
- db
- redis
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./:/var/www/html
- ./docker/nginx/bitrix.conf:/etc/nginx/conf.d/default.conf
db:
image: percona:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
volumes:
- db_data:/var/lib/mysql
redis:
image: redis:7-alpine
volumes:
db_data:
Плюсы: одинаковое окружение у всей команды, быстрый онбординг новых разработчиков, легко поднять десяток окружений для параллельной работы. Минусы: на продакшене Docker даёт накладные расходы по производительности (обычно незначительные, но зависят от конфигурации сети, файловой системы и нагрузки), требует дисциплины в работе с томами и секретами, добавляет слой абстракции, который нужно понимать всей команде. Для небольших проектов на одном сервере классическое развёртывание без контейнеров может быть проще.
Multi-environment: dev / stage / prod
Три окружения — минимум для коммерческой разработки на Битрикс. Локальная разработка ведётся на dev, тестирование перед выкаткой — на stage, боевой сервер — prod. Каждое окружение имеет свои настройки: пути к базе, ключи API, уровень логирования. Всё это удобно выносить в .env и подхватывать через сторонние библиотеки вроде symfony/dotenv. Замечу: .env — это не встроенный механизм Битрикс, а внешняя практика, которую нужно явно подключать в проекте.
Правило простое: .env никогда не попадает в репозиторий. В репозитории лежит .env.example с перечнем переменных, реальные значения настраиваются на каждом сервере отдельно.
Git-архитектура и .gitignore
Самая распространённая ошибка при создании сайтов на Битрикс — тащить в Git папку /bitrix целиком. Ядро платформы — это не ваш код, оно обновляется вендором, и его версионирование создаёт конфликты при каждом обновлении. Современный подход: весь кастомный код держится в /local, а ядро и пользовательские файлы не версионируются.
В репозиторий попадает только то, что относится к проекту: /local, конфиги, composer.json и composer.lock. Каталог /upload содержит пользовательские файлы (изображения, документы, загруженные через админку) и не должен версионироваться — в Git можно хранить только /upload/.htaccess или пустую структуру каталога, если это требуется для деплоя.
/bitrix/*
!/bitrix/.htaccess
/upload/*
!/upload/.htaccess
/local/cache/
/local/logs/
/vendor/
*.log
*.sql
*.bak
*.zip
.env
.env.*
!.env.example
.idea/
Если в проекте исторически есть кастомные шаблоны или компоненты внутри /bitrix, это исключение нужно явно оговорить и по возможности перенести в /local. Хранить /bitrix/templates и /bitrix/components в Git — устаревшая практика, которая приводит к конфликтам при обновлении ядра.
Плюсы: чистая история, нет конфликтов с ядром, быстрый clone. Минусы: нужно один раз аккуратно настроить, иначе рискуете случайно закоммитить ядро или, наоборот, потерять local/php_interface при обновлении.
Branching strategy (упрощённый GitFlow)
Для Битрикс-разработки хорошо работает упрощённый GitFlow. Две долгоживущие ветки: master — стабильная, с неё разворачивается production, и develop — ветка разработки, с неё идёт деплой на staging. Каждая задача ведётся в отдельной ветке feature/*, которая вливается в develop через merge request. Срочные правки — hotfix/*, они вливаются и в master, и в develop.
Плюсы: предсказуемость, никто не пушит в стабильную ветку напрямую, легко откатить неудачный релиз. Минусы: для проекта с одним разработчиком GitFlow — избыточная церемония, проще trunk-based development с короткоживущими ветками и частыми релизами.
Composer: управление зависимостями
Composer в Bitrix — это не про установку ядра, а про сторонние библиотеки. Логирование через Monolog, работа с REST API через Guzzle, внедрение зависимостей через php-di.
{
"require": {
"monolog/monolog": "^3.0",
"guzzlehttp/guzzle": "^7.0",
"php-di/php-di": "^7.0"
},
"autoload": {
"psr-4": {
"ProjectScope\\": "local/lib/"
},
"classmap": [
"local/components/project/*/src"
]
},
"config": {
"optimize-autoloader": true,
"sort-packages": true
}
}
Плюсы: стандарт индустрии, autoload вместо ручных require, простая установка обновлений. Минусы: на некоторых shared-хостингах composer недоступен, старые версии PHP не поддерживаются современными библиотеками. Для проектов на актуальном PHP 8.2+ проблем нет.
CI/CD: пайплайн build → test → deploy
При деплое через rsync критично исключить /bitrix и /upload — иначе опция --delete снесёт на сервере ядро платформы и пользовательские файлы, и проект перестанет работать в течение секунды. Помимо этого исключаются каталоги кэша, логи и локальные настройки:
stages:
- build
- test
- deploy
build:
stage: build
script:
- composer install --no-dev --optimize-autoloader
- npm ci && npm run build
test:
stage: test
script:
- vendor/bin/phpstan analyse
- vendor/bin/php-cs-fixer fix --dry-run --diff
- vendor/bin/phpunit
deploy:
stage: deploy
script:
- rsync -a --delete
--exclude=/bitrix
--exclude=/upload
--exclude=/local/cache
--exclude=/local/logs
--exclude=/bitrix/html_pages
--exclude=/.env
./ user@server:/var/www/domain.ru/
- ssh user@server "cd /var/www/domain.ru && composer install --no-dev"
Плюсы: автоматизация, воспроизводимость деплоя, откат через git revert. Минусы: первичная настройка требует времени, для небольших проектов с одним разработчиком сложность не всегда окупается. Но если релизы хотя бы раз в неделю — CI/CD оправдан. Исключения в rsync — не деталь, а обязательная часть пайплайна.
Backup strategy
Бэкап при разработке на Битрикс — это не «сделаем потом». Обязательны две вещи: дамп базы и копия файлов. Дамп делается через mysqldump с опцией --single-transaction, чтобы не блокировать таблицы.
mysqldump --single-transaction --routines --triggers \
--user=${DB_USER} --password=${DB_PASSWORD} \
${DB_NAME} | gzip > /backups/db_$(date +%Y%m%d_%H%M%S).sql.gz
Плюсы: минимальная страховка от катастрофы. Минусы: mysqldump на миллионном каталоге может занимать часы и потреблять много I/O. Для больших проектов лучше использовать Percona XtraBackup — он делает горячие бэкапы без блокировки таблиц.
Часть 2. База данных
Когда инфоблок избыточен
Инфоблоки — мощный инструмент, но каждое свойство — запись в отдельной таблице, каждый фильтр — JOIN. Для блога, новостей, каталога товаров инфоблок оправдан. Для справочника городов или списка статусов — нет. Признак: данные плоские, иерархии нет, полей немного, фильтрация простая.
Highload-блок или кастомная ORM-таблица (DataManager)
Highload-блок — генератор таблиц на основе D7 ORM, создаётся из админки, поддерживает UF-свойства, даёт готовый интерфейс. Собственная ORM-таблица — класс-наследник Bitrix\Main\Entity\DataManager, полный контроль над схемой, но интерфейс и работу с данными пишете сами.
Плюсы Highload-блока: быстро создать, готовый UI, не нужно писать код админки. Минусы: только простые индексы, нет внешних ключей, нет миграций. Плюсы DataManager: полный контроль над индексами и связями, миграции, типизация. Минусы: всё нужно писать самому, включая интерфейс.
Критерий: нужны составные индексы и связи — DataManager; данные плоские и нужен готовый интерфейс — Highload-блок. Для каталога с миллионом товаров Highload-блок часто не подходит именно из-за невозможности добавить составной индекс.
Миграции: MigrationRunner, up()/down(), таблица версий
Bitrix не имеет встроенного механизма миграций, поэтому нужен собственный раннер. Он состоит из трёх частей: таблица версий в базе, классы миграций с методами up() и down(), и раннер, который применяет только новые миграции.
Важно: пример ниже — учебный. В продакшене нужны транзакции на миграцию, блокировка от параллельного запуска, контрольные суммы, лимит попыток отката и логирование. Не копируйте код в боевой проект без адаптации.
Таблица версий создаётся один раз при инициализации:
CREATE TABLE project_migrations (
ID INT AUTO_INCREMENT PRIMARY KEY,
VERSION VARCHAR(255) NOT NULL UNIQUE,
APPLIED_AT DATETIME NOT NULL
);
Класс миграции — обычный PHP-класс с двумя методами. Никаких наследований от ядра, чтобы миграция не зависела от версии Bitrix:
<?php
class Migration20260101AddPhoneColumn
{
public function up(): void
{
$connection = \Bitrix\Main\Application::getConnection();
$connection->queryExecute("
ALTER TABLE project_orders
ADD COLUMN PHONE VARCHAR(20) DEFAULT NULL
");
}
public function down(): void
{
$connection = \Bitrix\Main\Application::getConnection();
$connection->queryExecute("
ALTER TABLE project_orders
DROP COLUMN PHONE
");
}
}
Раннер сканирует каталог с миграциями, сравнивает имена классов с записями в таблице версий и применяет только те, которых там нет. Откат вызывается вручную — down() нужен, когда миграция сломала прод и надо вернуться к прежней схеме:
<?php
class MigrationRunner
{
/** @var string Каталог с классами миграций */
private string $migrationsDir;
public function __construct(string $migrationsDir)
{
$this->migrationsDir = rtrim($migrationsDir, '/');
}
/**
* Применяет все новые миграции из каталога.
*
* @return array Список применённых версий
*/
public function run(): array
{
$applied = $this->getAppliedVersions();
$migrations = $this->discoverMigrations();
$appliedNow = [];
foreach ($migrations as $version => $class) {
if (in_array($version, $applied, true)) {
continue;
}
/** @var object $instance */
$instance = new $class();
if (!method_exists($instance, 'up')) {
throw new \RuntimeException("Migration {$class} has no up() method");
}
$instance->up();
$this->markApplied($version);
$appliedNow[] = $version;
}
return $appliedNow;
}
/**
* Откатывает указанную версию.
*
* @param string $version Версия миграции
* @return void
*/
public function rollback(string $version): void
{
$migrations = $this->discoverMigrations();
if (!isset($migrations[$version])) {
throw new \RuntimeException("Migration {$version} not found");
}
$class = $migrations[$version];
$instance = new $class();
if (!method_exists($instance, 'down')) {
throw new \RuntimeException("Migration {$class} has no down() method");
}
$instance->down();
$this->markRolledBack($version);
}
private function getAppliedVersions(): array
{
$connection = \Bitrix\Main\Application::getConnection();
$result = $connection->query('SELECT VERSION FROM project_migrations');
$versions = [];
while ($row = $result->fetch()) {
$versions[] = $row['VERSION'];
}
return $versions;
}
private function discoverMigrations(): array
{
$files = glob($this->migrationsDir . '/Migration*.php');
$migrations = [];
foreach ($files as $file) {
$class = basename($file, '.php');
if (!class_exists($class)) {
require_once $file;
}
$version = preg_replace('/^Migration(\d+).*$/', '$1', $class);
$migrations[$version] = $class;
}
ksort($migrations);
return $migrations;
}
private function markApplied(string $version): void
{
$connection = \Bitrix\Main\Application::getConnection();
$helper = $connection->getSqlHelper();
$connection->queryExecute(sprintf(
"INSERT INTO project_migrations (VERSION, APPLIED_AT) VALUES ('%s', NOW())",
$helper->forSql($version)
));
}
private function markRolledBack(string $version): void
{
$connection = \Bitrix\Main\Application::getConnection();
$helper = $connection->getSqlHelper();
$connection->queryExecute(sprintf(
"DELETE FROM project_migrations WHERE VERSION = '%s'",
$helper->forSql($version)
));
}
}
Запуск из CLI-скрипта на этапе деплоя:
<?php
require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';
$runner = new MigrationRunner(__DIR__ . '/migrations');
$applied = $runner->run();
echo 'Applied migrations: ' . implode(', ', $applied) . PHP_EOL;
Плюсы: схема на всех окружениях одинаковая, легко откатить, видно историю изменений. Минусы: ядро Bitrix не использует миграции, и если ваши сущности пересекаются с ядровыми таблицами, можно поймать неожиданные конфликты. Миграции стоит применять только к своим таблицам.
Индексация MySQL для каталога от 100 000 товаров
Штатный фасетный индекс Bitrix перестаёт справляться при 6–8 активных фильтрах. Нужны ручные индексы. Для запросов с коррелированным EXISTS по IBLOCK_ELEMENT_ID порядок колонок: (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE_ENUM).
ALTER TABLE b_iblock_element_prop_m14
ADD INDEX idx_prop_m14_element_prop_enum (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE_ENUM),
ALGORITHM=INPLACE, LOCK=NONE;
Плюсы: ускорение конкретных тяжёлых запросов в разы, полный контроль. Минусы: каждая лишняя колонка в индексе замедляет вставку и увеличивает размер БД, индексы не создают «на всякий случай» — только под конкретный запрос после EXPLAIN. На production ALTER TABLE выполняется с ALGORITHM=INPLACE, LOCK=NONE.
Очереди: таблица-очередь и сторонние брокеры
Тяжёлые операции не должны выполняться в момент запроса пользователя. Есть два уровня сложности, и каждый решает свой класс задач.
Таблица-очередь. Задачи складываются в свою таблицу project_queue, воркер раз в минуту читает пачку через SELECT ... FOR UPDATE SKIP LOCKED, обрабатывает и удаляет. Реализуется на чистом SQL и PHP, никаких внешних зависимостей. Хорошо работает до нескольких тысяч задач в час.
Важно: пример ниже — упрощённый. В продакшене нужны восстановление «зависших» задач по таймауту, лимит попыток, dead letter queue, идемпотентность обработчиков и валидация HANDLER по белому списку.
CREATE TABLE project_queue (
ID INT AUTO_INCREMENT PRIMARY KEY,
HANDLER VARCHAR(255) NOT NULL,
PAYLOAD TEXT NOT NULL,
STATUS ENUM('new', 'in_progress', 'done', 'failed') DEFAULT 'new',
ATTEMPTS INT DEFAULT 0,
CREATED_AT DATETIME NOT NULL,
UPDATED_AT DATETIME DEFAULT NULL,
INDEX idx_status_created (STATUS, CREATED_AT)
);
// Постановка задачи
$connection = \Bitrix\Main\Application::getConnection();
$helper = $connection->getSqlHelper();
$connection->queryExecute(sprintf(
"INSERT INTO project_queue (HANDLER, PAYLOAD, CREATED_AT) VALUES ('%s', '%s', NOW())",
$helper->forSql($handler),
$helper->forSql(json_encode($payload))
));
// Воркер, запускается через cron раз в минуту
$connection = \Bitrix\Main\Application::getConnection();
$connection->queryExecute("START TRANSACTION");
$result = $connection->query("
SELECT ID, HANDLER, PAYLOAD
FROM project_queue
WHERE STATUS = 'new'
ORDER BY ID
LIMIT 100
FOR UPDATE SKIP LOCKED
");
$tasks = [];
while ($row = $result->fetch()) {
$tasks[] = $row;
}
if ($tasks) {
$ids = array_column($tasks, 'ID');
$connection->queryExecute(
"UPDATE project_queue SET STATUS = 'in_progress' WHERE ID IN (" . implode(',', $ids) . ")"
);
}
$connection->queryExecute("COMMIT");
foreach ($tasks as $task) {
try {
$handler = $task['HANDLER'];
$payload = json_decode($task['PAYLOAD'], true);
call_user_func($handler, $payload);
$connection->queryExecute("DELETE FROM project_queue WHERE ID = " . (int)$task['ID']);
} catch (\Throwable $e) {
$connection->queryExecute(sprintf(
"UPDATE project_queue SET STATUS = 'new', ATTEMPTS = ATTEMPTS + 1 WHERE ID = %d",
(int)$task['ID']
));
}
}
Плюсы таблицы-очереди: минимум инфраструктуры, полный контроль, легко отлаживать. Минусы: не масштабируется горизонтально, нет приоритетов, нет dead letter queue, на высоких нагрузках таблица становится узким местом.
Сторонние брокеры. Bitrix не имеет стабильного публичного API для промышленных очередей. В ядре есть пространство имён Bitrix\Main\Messenger, но оно относится к внутренним механизмам фреймворка, плохо документировано и может меняться между версиями. Использовать его в продакшене на 2026 год — рискованно.
Для высоконагруженных проектов промышленный стандарт — Symfony Messenger с транспортом RabbitMQ или Redis. Есть готовые модули, которые интегрируют его в Bitrix без переписывания ядра. Конкретные пакеты и их актуальность нужно проверять на момент внедрения: экосистема сторонних модулей для Bitrix меняется, и не все решения поддерживают PHP 8.2/8.3 и текущие релизы ядра.
Плюсы сторонних брокеров: промышленная надёжность, масштабирование, приоритеты, dead letter queue, отложенные сообщения. Минусы: дополнительная инфраструктура, нужно понимать AMQP, нужен Supervisor для воркеров, нужен мониторинг очередей. Для проектов с десятками тысяч задач в час RabbitMQ оправдан; для небольших проектов хватает таблицы-очереди.
Часть 3. Вёрстка и шаблонизация
Архитектура local/templates
Шаблон сайта — это не место для бизнес-логики. В header.php только подключение стилей, вывод шапки и открытие контейнера. Если в header.php появился вызов CIBlockElement::GetList — это ошибка. Данные готовятся в компонентах, шаблон только отображает. Стили разбиваются по компонентам, подключаются через Asset::addCss() в component_epilog.php.
Fluid-вёрстка и Container Queries
Вместо сотен @media — clamp() для типографики и отступов, Container Queries для изоляции стилей. Карточка товара в сетке каталога и в слайдере — один компонент, адаптируется к ширине родителя. Контейнер ставится на обёртку каждой карточки, а не на общую сетку.
.product-card {
container-type: inline-size;
container-name: product-card;
}
@container product-card (min-width: 400px) {
.product-card__inner {
flex-direction: row;
}
}
Плюсы: компоненты переиспользуются без правок, нет JS-костылей для измерения ширины блока, меньше медиа-запросов. Минусы: поддержка Container Queries только в современных браузерах (95%+ на 2026 год), старые браузеры получат фиксированную вёрстку. Для проектов на Битрикс с B2B-аудиторией, где ещё встречаются устаревшие браузеры, требуется progressive enhancement.
Шаблонизаторы: Twig в Битриксе
Bitrix поддерживает сторонние шаблонизаторы только для шаблонов компонентов. Подключение Twig через arCustomTemplateEngines.
Плюсы: лаконичный синтаксис, явное разделение логики и отображения, защита от случайного вызова Bitrix API. Минусы: дополнительный слой абстракции, чуть ниже производительность, разработчикам нужно учить синтаксис. Для команды из нескольких разработчиков Twig оправдан; для одного разработчика нативный template.php проще.
Часть 4. Качество кода
PHPStan: статический анализ
parameters:
level: 5
paths:
- local/lib
scanDirectories:
- bitrix/modules
ignoreErrors:
- '#Call to an undefined method Bitrix\\Main\\Entity\\DataManager::#'
Плюсы: ловит ошибки до запуска, помогает в рефакторинге. Минусы: на Bitrix много ложных срабатываний из-за динамических методов, часть ошибок приходится игнорировать. Уровень 5 — разумный компромисс между пользой и шумом.
PHP-CS-Fixer и EditorConfig
PHP-CS-Fixer приводит код к единому стилю через .php-cs-fixer.php. EditorConfig настраивает отступы на уровне редактора. Плюсы: единый стиль, меньше споров в ревью, чистая история diff. Минусы: автозапуск на CI может «дёргать» чужие коммиты, лучше запускать через pre-commit hook.
Тесты: PHPUnit и Codeception
class OrderServiceTest extends BitrixTestCase
{
public function testCreateOrder(): void
{
$service = new OrderService();
$result = $service->create(['productId' => 1, 'quantity' => 2]);
$this->assertInstanceOf(Order::class, $result);
}
}
Важно: BitrixTestCase — не встроенный класс Битрикс. Обычно он берётся из сторонних пакетов, например webarchitect609/bitrix-taxidermist, и требует отдельной настройки. Проверьте актуальность пакета под вашу версию PHP и ядра.
Плюсы: регрессия закрыта, рефакторинг безопасен, документация через тесты. Минусы: Bitrix плохо изолируется для юнит-тестов, приходится использовать сторонние решения, что усложняет настройку. Для небольших проектов полноценное покрытие тестами часто нерентабельно.
Часть 5. Мониторинг и логирование
Grafana + Prometheus + Sentry
Мониторинг должен показывать не только «железо», но и бизнес-метрики: TTFB, количество запросов, ошибки. Grafana и Prometheus дают единый дашборд. Sentry ловит исключения в реальном времени.
Плюсы: единая точка правды, история изменений, алерты, быстрая диагностика. Минусы: инфраструктура требует отдельного сервера, настройка занимает время. Для небольших проектов часто хватает Sentry и встроенных метрик.
Monolog: логирование в Битрикс
$logger = new \Monolog\Logger('app');
$logger->pushHandler(new \Monolog\Handler\RotatingFileHandler(
$_SERVER['DOCUMENT_ROOT'] . '/local/logs/app.log',
30,
\Monolog\Logger::INFO
));
$logger->info('Order created', ['orderId' => $orderId]);
Плюсы: структурированные логи, ротация, разные каналы. Минусы: если писать лог в файл на каждой операции, диск заполнится за неделю. Нужны ротация, лимиты и Sentry для ошибок.
Часть 6. Безопасность
SQL-инъекции, XSS, CSRF
Всегда используйте SqlHelper::forSql() или параметризованные запросы. Для числовых — приведение к int. Все данные в шаблоне — через htmlspecialcharsbx(). В формах — bitrix_sessid_post(), на приёме — check_bitrix_sessid().
CSP и HTTP-заголовки безопасности
Content Security Policy для Bitrix нельзя включать «в лоб» с unsafe-inline и unsafe-eval — это не CSP, а его имитация. Ядро и большинство модулей Bitrix используют inline-скрипты и динамическую генерацию кода, поэтому жёсткая политика ломает админку и часть публичных страниц.
Правильный подход — начать с режима Content-Security-Policy-Report-Only, собрать отчёты о том, какие источники и inline-скрипты реально используются, и только потом включать боевой заголовок с nonce или хешами для inline-кода. Для приёма отчётов используйте report-to (современная замена устаревающего report-uri) и отдельный endpoint. На практике для Bitrix часто ограничиваются frame-ancestors 'self' и upgrade-insecure-requests, а полный CSP выносят в отдельную задачу.
# Отдельные заголовки, которые безопасны для Bitrix из коробки
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin-when-cross-origin";
# CSP в режиме отчётов, без блокировки
add_header Content-Security-Policy-Report-Only "default-src 'self'; report-to csp-endpoint";
Плюсы: защита от XSS, clickjacking, утечки через реферрер. Минусы: жёсткий CSP ломает часть модулей Bitrix — придётся разрешать конкретные внешние домены, а это ослабляет защиту. Настраивается аккуратно, тестируется в режиме report-only перед включением.
Cookies с флагами HttpOnly, Secure, SameSite
Кука сессии Bitrix должна иметь флаги HttpOnly, Secure и SameSite=Lax или Strict. Без них интернет-магазин на Битрикс уязвим к перехвату сессии. Настраивается в php.ini через session.cookie_httponly и session.cookie_secure.
Права на файлы, закрытый /bitrix
Базовые права: 644 для файлов, 755 для папок. Каталоги, в которые должен писать веб-сервер (/upload, /bitrix/cache, /bitrix/managed_cache, /bitrix/html_pages, /local/logs), требуют отдельной настройки владельца и прав — обычно их владельцем становится пользователь www-data или nginx. Файл dbconn.php должен быть недоступен извне.
Закрывать /bitrix целиком нельзя — сломается отдача статики (/bitrix/js, /bitrix/css, /bitrix/images, /bitrix/templates). Правильный подход: запретить выполнение PHP внутри /bitrix, кроме разрешённых точек (/bitrix/admin, /bitrix/urlrewrite.php, некоторые служебные скрипты), а статику оставить доступной.
# Запрет выполнения PHP в /bitrix, кроме разрешённых точек
location ~ ^/bitrix/(?!admin|urlrewrite\.php|tools/).*\.php$ {
deny all;
return 403;
}
# Отдача статики из /bitrix
location ~* ^/bitrix/.*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
expires 30d;
access_log off;
}
Часть 7. SEO
ЧПУ, модуль search
ЧПУ настраивается через urlrewrite.php и правила в компонентах. Модуль search отвечает за индексацию и полнотекстовый поиск. Плюс: правильные ЧПУ закладываются сразу. Минус: менять их потом больно, все ссылки окажутся битыми.
sitemap.xml и robots.txt
sitemap.xml генерируется модулем search или сторонними решениями, разбивается на файлы по 50 000 URL. robots.txt закрывает технические разделы и открывает каталог.
Микроразметка Schema.org
Для JSON-LD нельзя использовать htmlspecialcharsbx(): он превращает кавычки и спецсимволы в HTML-сущности, из-за чего JSON становится невалидным или искажённым. Используйте json_encode():
<?php
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $arResult['NAME'],
'offers' => [
'@type' => 'Offer',
'price' => $arResult['PRICE'],
'priceCurrency' => 'RUB',
],
];
?>
<script type="application/ld+json">
<?= json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>
</script>
Плюсы: улучшает сниппеты, повышает CTR. Минусы: ошибки в разметке ловятся через Google Search Console уже после публикации. Правила Schema.org для Product регулярно меняются.
Часть 8. Интеграции: 1С и современные CRM
Для интернет-магазина на Битрикс интеграции — это половина ценности. Без обмена с 1С каталог и остатки будут расходиться с реальностью; без CRM теряется работа с клиентской базой, воронка продаж и маркетинг. Ниже — базовые сценарии, которые встречаются почти в каждом проекте.
Интеграция с 1С: CommerceML, REST API, промежуточная шина
Три сценария обмена с 1С: УТ, ERP, КА:
CommerceML — штатный механизм Bitrix. Выгружает каталог, цены, остатки, заказы через exchange1c.
Плюсы: работает из коробки, документация, поддержка вендора.
Минусы: медленный на больших каталогах, обмен по расписанию (не real-time), плохо переваривает сложные структуры свойств и торговых предложений, кастомизация формата ограничена.
REST API 1С (через http-сервисы или OData).
Плюсы: гибкость, можно запрашивать только нужные данные, real-time обмен остатками, легко подключить к очередям.
Минусы: требует доработки на стороне 1С (не во всех конфигурациях есть готовые сервисы), нужен стабильный канал, нужен middleware, если систем больше двух.
Промежуточная шина (RabbitMQ, Kafka, 1С:Шина).
Плюсы: масштабируется, развязывает системы, гарантирует доставку, легко добавлять новых потребителей.
Минусы: дорого по инфраструктуре, требует команды, которая умеет это поддерживать. Оправдано только для больших проектов с несколькими системами.
На этапе проектирования важно определить мастер-данные: цены и остатки — в 1С, контент — на сайте, заказы — на сайте, выгружаются в 1С. Если это не зафиксировать, через год каталог придётся переписывать.
Битрикс24: CRM и портал для команды
Битрикс24 — это и CRM, и корпоративный портал, и генератор лидов, и хранилище сделок. Интеграция с сайтом на Битрикс обычно делается через REST API и вебхуки.
Что даёт: лиды с форм сайта попадают в CRM автоматически, сделки синхронизируются с заказами, клиентская база объединяется с историей покупок, воронка строится по фактическим заказам, сквозная аналитика от рекламы до выручки.
Плюсы: родная интеграция с Bitrix, единая экосистема, готовые REST-методы, встроенный телефон и почта, не нужно ставить отдельный сервер. Минусы: тарифы растут с числом пользователей, часть интеграций требует «коробочной» версии, кастомизация ограничена рамками платформы. Для проектов, где команда уже работает в Битрикс24, интеграция окупается быстро.
RetailCRM: специализированная CRM для e-commerce
RetailCRM — CRM, заточенная под интернет-магазины и омниканальную торговлю. Работает с заказами, складом, доставкой, маркетингом.
Что даёт: единая карточка клиента со всеми заказами, интеграция с десятками служб доставки и платёжных систем, автоматизация триггерных рассылок, программа лояльности, сквозная аналитика, API с лимитами под нагрузку интернет-магазина.
Плюсы: заточена под e-commerce, интеграция с Bitrix через готовый модуль, много готовых сценариев автоматизации, поддержка СМС, email, мессенджеров, абонентская плата не завязана на число пользователей. Минусы: не заменяет корпоративный портал, ограниченные возможности по не-commerce процессам, чуть менее гибкая кастомизация, чем у Битрикс24. Для среднего интернет-магазина на Битрикс с потоком заказов от 100 в день RetailCRM окупается за счёт автоматизации.
AmoCRM: воронка продаж и лидогенерация
AmoCRM — CRM с сильной воронкой продаж, популярна в B2B и услугах. Интеграция с сайтом через REST API и вебхуки, есть готовые модули для Bitrix.
Что даёт: гибкая воронка с автоматизацией, работа с лидами из разных источников, цифровая воронка с триггерами, интеграция с телефонией, отчёты по конверсии на каждом этапе.
Плюсы: одна из лучших воронок на рынке, много готовых интеграций, гибкие цифровые воронки, широкая партнёрская сеть внедренцев. Минусы: оплата за пользователя, ограничения по числу сделок на тарифах, для интернет-магазина с большим потоком заказов тарифы быстро становятся дорогими. AmoCRM оправдана в проектах, где продажи идут через менеджеров, а не через корзину: B2B, услуги, сложные продукты.
Какую CRM выбрать
- Битрикс24 — если команда уже работает в экосистеме Битрикс, нужен и портал, и CRM, и учёт в одном месте.
- RetailCRM — если это интернет-магазин с потоком заказов, важны интеграции с доставкой, маркетинг, программы лояльности.
- AmoCRM — если продажи идут через менеджеров, длинный цикл сделки, важен B2B и услуги.
Во всех трёх случаях интеграция с сайтом на Битрикс строится через REST API. Заказы и лиды передаются в CRM, статусы и оплаты возвращаются обратно, история покупок подтягивается в карточку клиента. Это стандартный паттерн, который стоит закладывать на этапе проектирования, а не после запуска.
Часть 9. Практика
Что чаще всего ломается при внедрении
Первое — композитный кэш. Включают, но в Nginx не добавляют блок отдачи — эффекта нет. Второе — очереди: ставят сторонний брокер, но забывают про Supervisor, воркеры падают при первом сбое. Третье — миграции: на staging применяют вручную, на production забывают, схема расходится. Четвёртое — CSP: включают жёстко с unsafe-inline, думают, что защитились, а по факту это не CSP. Пятое — бэкапы на тот же диск, где лежит сайт. Шестое — интеграция с CRM без очереди: при скачке заказов API отваливается по лимитам, заказы теряются. Седьмое — rsync --delete без исключений на первом же деплое сносит /bitrix и /upload. Восьмое — забывают про client_max_body_size, и загрузка файлов через админку молча падает на 4 МБ.
Как проверить, что всё работает
Прогон через Монитор качества Bitrix — обязательный минимум. Проверяются веб-окружение, интеграция дизайна, безопасность, производительность, размещение на хостинге. Отдельно проверяется, что агенты запускаются через cron, а не на хитах, что /bitrix не в Git, что в dbconn.php не лежат боевые пароли. Интеграции тестируются на реальных данных: пробный заказ идёт в CRM, синхронизация возвращает статус, очередь не теряет сообщения при перезапуске воркера.
Резюме и чек-лист перед запуском
Разработка на Битрикс без легаси — это про инфраструктуру, которая позволяет развивать проект годами. Сервер на чистом стеке, Docker, Git только с проектным кодом, Composer, D7 ORM и Highload-блоки, ручные индексы, Fluid-вёрстка, интеграции с 1С и CRM, агенты на cron, очереди, CI/CD, тесты, мониторинг, безопасность, SEO.
- Инфраструктура: чистый стек
Nginx + PHP-FPM 8.2/8.3 + Percona; композит отдаётся черезNginx;/bitrix/html_pages/закрыт от прямого доступа;client_max_body_sizeподнят до 128 МБ; статика кэшируется. - Docker:
docker-compose.ymlдля локальной разработки; отдельныйdocker-compose.prod.ymlдля production. - Git: только
/local, конфиги иcomposer.json; ядро и/uploadв.gitignore;.envне коммитится. - Branching:
masterдля production,developдля staging,feature/*для задач. - CI/CD: пайплайн build, test, deploy;
rsyncпоSSHс исключениями/bitrix,/upload,.env. - Backup: ежедневный
mysqldumpс--single-transaction; копия файлов; хранение 7–30 дней на отдельном сервере. - База данных:
Highload-блокидля плоских справочников;DataManagerдля таблиц с составными индексами; миграции черезMigrationRunnerс таблицей версий. - Очереди: таблица-очередь для простых задач; сторонний брокер (
Symfony Messenger + RabbitMQ) для высоких нагрузок; воркеры подSupervisor. - Вёрстка:
clamp()иContainer Queries; контейнер на обёртке каждой карточки. - Качество кода:
PHPStan,PHP-CS-Fixer,EditorConfig; тесты черезPHPUnitиCodeception. - Мониторинг:
Grafana + Prometheus,Sentry,Monolog. - Безопасность: экранирование ввода,
bitrix_sessid_post(), CSP в режиме отчётов, флагиHttpOnly/Secure/SameSite, закрытый/bitrixот выполнения PHP. - SEO: ЧПУ,
sitemap.xml,robots.txt,Schema.orgчерезjson_encode(). - Интеграции: 1С через
CommerceMLилиREST API; CRM (Битрикс24,RetailCRM,AmoCRM) черезREST APIи вебхуки; очереди для устойчивости обмена. - Монитор качества: обязательные тесты пройдены; критические ошибки безопасности устранены.
Материал получился обзорным — каждая тема заслуживает отдельной статьи. Дальше решать вам: углублять конкретное направление, собирать по нему полноценный инженерный гайд или оставить как краткий ориентир при развёртывании Битрикс-проектов.
Комментарии