Блог разработчика 1С-Битрикс

Как стать разработчиком на 1С-Битрикс: пошаговый путь от новичка до профессионала

Хочешь войти в веб-разработку, работать с корпоративными сайтами и интернет-магазинами и при этом быть востребованным? 1С-Битрикс — крепкая платформа с большим рынком. Ниже — практическое руководство: что учить, как тренироваться, какие инструменты ставить и как собрать портфолио, чтобы уверенно брать реальные проекты.

Как стать разработчиком на 1С-Битрикс

Кто такой разработчик 1С-Битрикс и чем он занимается

Разработчик 1С-Битрикс — это бэкенд/фуллстек-инженер, который:

  • проектирует структуру сайта (инфоблоки, highload-блоки, модули);
  • пишет компоненты и шаблоны, дорабатывает готовые;
  • интегрирует платёжные системы, 1С/ERP/CRM, сервисы доставки;
  • оптимизирует производительность (кэш, композит, CDN), безопасность;
  • автоматизирует рутину миграциями, CI/CD и тестами;
  • поддерживает и развивает проект после релиза.

В работе ты будешь много писать PHP (ядро Bitrix), достаточно уверенно владеть JavaScript (включая BX.* API, Fetch/AJAX и иногда Vue/React), уверенно читать HTML/CSS, работать с SQL и Git.

Необходимые базовые знания (HTML, CSS, JS, PHP, SQL)

Минимум, с которым комфортно стартовать

  • HTML5/CSS3: семантика, адаптив, сетки (Flex/Grid), БЭМ-подход.
  • JavaScript: современный синтаксис (ES6+), Fetch/AJAX, модули, события. Для Bitrix пригодится знание BX.ajax, BX.ready, BX.bind и пр.
  • PHP 8+: типы, ООП, исключения, пространства имён, Composer-автозагрузка, PSR-12.
  • SQL: SELECT/INSERT/UPDATE/DELETE, индексы, JOIN, транзакции.
  • Git: feature-ветки, Pull Request, rebase/merge, git-flow.
  • Linux/Docker: базовые команды, работа с контейнерами, PHP-расширениями, Nginx/Apache, MariaDB/MySQL.

Совет: подтяни синтаксис и ООП в PHP, затем закрепи на мини-скриптах. Это даст уверенность при погружении в Bitrix-ядро (namespace Bitrix\…).

Изучение архитектуры и ядра 1С-Битрикс

Куда смотреть в проекте

  • /local/ — твоя зона разработки: компоненты, шаблоны, модули. Не правь код в /bitrix/ (иначе обновления сотрут правки).
  • local/components/ — собственные компоненты.
  • local/templates/ — шаблоны сайта и стили.
  • local/modules/ — кастомные модули.
  • local/php_interface/ — точка входа для инициализации (события, автолоад).

Ключевые части платформы

  • D7-ядро (современный слой): пространства имён, ORM, события, сервисы. Используй его вместо устаревших вызовов.
  • ORM: Bitrix\Main\ORM и таблицы модулей (например, Bitrix\Highloadblock\HighloadBlockTable). Для инфоблоков часто комбинируют ORM и удобные классы CIBlockElement из-за полей/свойств.
  • События и обработчики: Bitrix\Main\EventManager::getInstance()->addEventHandler(...).
  • Кэш: кэш компонентов, Bitrix\Main\Data\Cache, tagged cache для инвалидации по тегам.
  • Настройки проекта: .settings.php, .settings_extra.php, dbconn.php — разделяй dev/test/prod.

Что считать «современным» в коде

  • \Bitrix\Main\Loader::includeModule('iblock');
  • ✅ пространства имён и автозагрузка, строгие типы declare(strict_types=1);
  • ✅ ORM/сервисы, исключения, явная работа с зависимостями
  • CModule::IncludeModule() (старый стиль)
  • ❌ прямые mysql_* вызовы
  • ❌ правки в /bitrix/ вместо /local/

Работа с компонентами, модулями и шаблонами

Структура своего компонента


/local/components/vendor/books.list/
  .description.php
  .parameters.php
  class.php            // логика компонента
  templates/.default/
    template.php
    style.css
    script.js
    
  • .description.php — имя, категория.
  • .parameters.php — параметры в визуальном редакторе.
  • class.php — класс компонента (D7-подход).
  • templates/... — верстка и JS.

Базовый каркас компонента (D7, кэш, AJAX-actions)


<?php
declare(strict_types=1);

use Bitrix\Main\Loader;
use Bitrix\Main\UI\PageNavigation;
use Bitrix\Main\Data\Cache;
use Bitrix\Main\Engine\Contract\Controllerable;
use Bitrix\Main\Engine\ActionFilter;
use Bitrix\Main\Engine\CurrentUser;

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) { die(); }

class BooksListComponent extends CBitrixComponent implements Controllerable
{
    public function onPrepareComponentParams($params): array
    {
        $params['IBLOCK_ID'] = (int)($params['IBLOCK_ID'] ?? 0);
        $params['PAGE_SIZE'] = max(1, (int)($params['PAGE_SIZE'] ?? 10));
        $params['CACHE_TIME'] = (int)($params['CACHE_TIME'] ?? 3600);
        return $params;
    }

    public function configureActions(): array
    {
        return [
            'like' => [
                'prefilters' => [
                    new ActionFilter\HttpMethod(['POST']),
                    new ActionFilter\Authentication(),
                    new ActionFilter\Csrf(),
                ],
            ],
        ];
    }

    protected function getFilter(): array
    {
        $request = \Bitrix\Main\Context::getCurrent()->getRequest();
        $author = trim((string)$request->get('author'));
        $filter = [
            'IBLOCK_ID' => $this->arParams['IBLOCK_ID'],
            'ACTIVE'    => 'Y',
        ];
        if ($author !== '') {
            $filter['PROPERTY_AUTHOR'] = $author;
        }
        return $filter;
    }

    protected function loadItems(): void
    {
        if (!Loader::includeModule('iblock')) {
            throw new \RuntimeException('Модуль iblock недоступен');
        }
        $cache = Cache::createInstance();
        $nav   = new PageNavigation('page');
        $nav->setPageSize($this->arParams['PAGE_SIZE'])->initFromUri();
        $cacheKey = md5(serialize([$this->getFilter(), $nav->getCurrentPage(), $nav->getPageSize()]));
        $cacheDir = '/books/list';
        if ($cache->initCache($this->arParams['CACHE_TIME'], $cacheKey, $cacheDir)) {
            $this->arResult = $cache->getVars();
            return;
        }
        if ($cache->startDataCache()) {
            $select = [
                'ID','IBLOCK_ID','NAME','DETAIL_PAGE_URL','PREVIEW_TEXT','DATE_ACTIVE_FROM',
                'PROPERTY_AUTHOR',
            ];
            $res = \CIBlockElement::GetList(
                ['SORT' => 'ASC', 'ID' => 'DESC'],
                $this->getFilter(),
                false,
                [
                    'iNumPage'        => $nav->getCurrentPage(),
                    'nPageSize'       => $nav->getPageSize(),
                    'checkOutOfRange' => true,
                ],
                $select
            );
            $items = [];
            $nav->setRecordCount($res->NavRecordCount);
            while ($el = $res->GetNextElement()) {
                $f = $el->GetFields();
                $p = $el->GetProperties();
                $items[] = [
                    'ID'           => (int)$f['ID'],
                    'NAME'         => $f['~NAME'],
                    'URL'          => $f['~DETAIL_PAGE_URL'],
                    'PREVIEW_TEXT' => $f['~PREVIEW_TEXT'],
                    'AUTHOR'       => $p['AUTHOR']['~VALUE'] ?? null,
                ];
            }
            $this->arResult = [
                'ITEMS' => $items,
                'NAV'   => $nav,
                'FILTER'=> ['AUTHOR' => \Bitrix\Main\Text\HtmlFilter::encode($this->getFilter()['PROPERTY_AUTHOR'] ?? '')],
            ];
            $cache->endDataCache($this->arResult);
        }
    }

    public function executeComponent(): void
    {
        $this->loadItems();
        $this->includeComponentTemplate();
    }

    public function likeAction(int $id): array
    {
        $userId = (int)CurrentUser::get()->getId();
        if ($userId <= 0) {
            throw new \Bitrix\Main\SystemException('Требуется авторизация');
        }
        \Bitrix\Main\Loader::includeModule('highloadblock');
        $hl = \Bitrix\Highloadblock\HighloadBlockTable::getList([
            'filter' => ['=NAME' => 'BookLikes'],
            'limit'  => 1,
        ])->fetch();
        if (!$hl) {
            throw new \Bitrix\Main\SystemException('HL-блок BookLikes не найден');
        }
        $entity    = \Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hl);
        $dataClass = $entity->getDataClass();
        $exists = $dataClass::getList([
            'filter' => ['UF_USER_ID' => $userId, 'UF_ITEM_ID' => $id],
            'limit'  => 1,
        ])->fetch();
        if ($exists) {
            $dataClass::delete((int)$exists['ID']);
            $liked = false;
        } else {
            $dataClass::add(['UF_USER_ID' => $userId, 'UF_ITEM_ID' => $id]);
            $liked = true;
        }
        $count = $dataClass::getCount(['UF_ITEM_ID' => $id]);
        return ['liked' => $liked, 'count' => $count];
    }
}
    

Шаблон компонента (фрагмент)

templates/.default/template.php


<?php if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die(); ?>
<form method="get" class="books-filter">
  <label>
    Автор:
    <input type="text" name="author" value="<?= $arResult['FILTER']['AUTHOR'] ?>">
  </label>
  <button type="submit">Фильтровать</button>
</form>
<ul class="books">
  <?php foreach ($arResult['ITEMS'] as $item): ?>
    <li class="book">
      <a href="<?= $item['URL'] ?>"><?= htmlspecialcharsbx($item['NAME']) ?></a>
      <?php if ($item['AUTHOR']): ?>
        <div class="book__meta">Автор: <?= htmlspecialcharsbx($item['AUTHOR']) ?></div>
      <?php endif; ?>
      <div class="book__text"><?= $item['PREVIEW_TEXT'] ?></div>
      <button class="book__like" data-like-id="<?= (int)$item['ID'] ?>">
        ❤ <span data-like-count>0</span>
      </button>
    </li>
  <?php endforeach; ?>
</ul>
<?php
$APPLICATION->IncludeComponent(
  'bitrix:main.pagenavigation',
  '',
  [
    'NAV_OBJECT' => $arResult['NAV'],
    'SEF_MODE'   => 'N',
  ],
  false
);
    

templates/.default/script.js


BX.ready(function () {
  document.addEventListener('click', function (e) {
    const btn = e.target.closest('[data-like-id]');
    if (!btn) return;
    const id = parseInt(btn.dataset.likeId, 10);
    BX.ajax.runComponentAction('vendor:books.list', 'like', {
      mode: 'class',
      data: { id: id }
    }).then(function (response) {
      const data = response.data;
      btn.classList.toggle('is-liked', !!data.liked);
      const cnt = btn.querySelector('[data-like-count]');
      if (cnt) cnt.textContent = data.count;
    }).catch(function (err) {
      const message = (err && err.errors && err.errors[0] && err.errors[0].message) || 'Ошибка';
      alert(message);
    });
  });
});
    

Практика: создание простого проекта «с нуля»

Цель: одностраничный каталог книг с фильтром по автору и лайками.

  1. Подними окружение
    Docker-композ: Nginx + PHP-FPM + MariaDB. В PHP добавь расширения: mbstring, intl, zip, gd/imagick, opcache, mysqli. Включи xdebug для отладки (dev-сборка).
  2. Установи чистый Битрикс
    Разворачивай с пустым шаблоном. Сразу создай /local/ и настрой в IDE (PhpStorm) инспекции, PHPStan/Psalm и PHP-CS-Fixer.
  3. Создай инфоблок «Книги»
    Поля: Название, Анонс. Свойства: AUTHOR (строка). Добавь пару тестовых элементов.
  4. Сделай HL-блок BookLikes
    Поля: UF_ITEM_ID (int, индекс), UF_USER_ID (int, индекс). Это наш счётчик лайков.
  5. Собери компонент vendor:books.list
    Положи код из раздела выше в /local/components/vendor/books.list/.
    Параметры: IBLOCK_ID, PAGE_SIZE=10, CACHE_TIME=3600.
  6. Подключи на страницу
    На странице /books/index.php:

<?php
require($_SERVER['DOCUMENT_ROOT'].'/bitrix/header.php');
$APPLICATION->SetTitle('Каталог книг');
$APPLICATION->IncludeComponent('vendor:books.list','',[
  'IBLOCK_ID'  => 3,      // подставь ID инфоблока
  'PAGE_SIZE'  => 10,
  'CACHE_TIME' => 3600
]);
require($_SERVER['DOCUMENT_ROOT'].'/bitrix/footer.php');
    

7. Проверь кэш и навигацию
Меняй фильтр — кэш-ключ должен учитывать автора и страницу. Для точной инвалидации при изменении инфоблока подключай tagged cache.

Изучение архитектуры глубже: ORM, события, кэш

ORM-пример: Highload-блок как сущность


use Bitrix\Highloadblock\HighloadBlockTable;
use Bitrix\Main\Loader;
Loader::includeModule('highloadblock');
$hl = HighloadBlockTable::getByPrimary(5)->fetchObject(); // ID HL-блока
$entity = HighloadBlockTable::compileEntity($hl);
$Likes  = $entity->getDataClass();
$list = $Likes::getList([
  'filter' => ['UF_ITEM_ID' => 123],
  'select' => ['ID','UF_USER_ID','UF_ITEM_ID']
])->fetchCollection();
    

События (пример — после добавления элемента инфоблока)


use Bitrix\Main\EventManager;
EventManager::getInstance()->addEventHandler(
  'iblock',
  'OnAfterIBlockElementAdd',
  static function(array $fields) {
    if ((int)$fields['IBLOCK_ID'] === 3) {
      // Очистить тег кэша при изменениях каталога книг
      $tc = new \Bitrix\Main\Data\TaggedCache();
      $tc->clearByTag('iblock_id_3');
    }
  }
);
    

Tagged cache в компоненте


$tagged = new \Bitrix\Main\Data\TaggedCache();
$tagged->startTagCache($cacheDir);
$tagged->registerTag('iblock_id_'.$this->arParams['IBLOCK_ID']);
$tagged->endTagCache();
    

Где брать реальные задачи и как собирать портфолио

Источники задач:

  • Свой мини-проект (как наш каталог) — выложи код в публичный репозиторий (например, Git).
  • Волонтёрство для НКО/локального бизнеса: лендинги, каталоги, блоги на Bitrix.
  • Микро-задачи: правки компонентов, миграции, интеграция оплаты/доставки, оптимизация скорости.
  • Участие в командных пет-проектах: роль backend, devops или интегратор.

Что положить в портфолио:

  • 2–3 проекта разных типов (контент-сайт, каталог/магазин, интеграция).
  • Код компонента с AJAX-action, пример модуля, пример миграции (создание инфоблока/HL-блока кодом).
  • Скриншоты админки и витрины, краткое описание задач и измеримые результаты (время загрузки, конверсия, TTFB до/после).

Как презентовать:

  • Короткие README: стек, зачем, как запустить (Docker-композ), что реализовано.
  • Нормальные коммиты, линтеры, CI (PHPStan/Psalm, тесты).
  • Пара абзацев про архитектурные решения и компромиссы.

Сертификация и карьерный рост

Линейка ролей:

  • Junior Bitrix Developer: компоненты, шаблоны, инфоблоки, базовый кэш, простые интеграции.
  • Middle: сложные компоненты, highload-структуры, миграции, интеграции с 1С/CRM, безопасность, композит, SPA/SSR-витрины.
  • Senior/Team Lead: архитектура, модули, highload-нагрузка, шардирование, DevOps, аудит, менторство.

Сертификация:

  • «Разработчик Bitrix Framework» — концентрируется на ядре, компонентах, ORM и кэше.
  • «Администратор» — про инфраструктуру, композит, производительность.
  • «Интеграция с 1С» — обмен, каталоги, цены/остатки.

Готовься по задачам из реальных проектов: компоненты с кэшем, события, ORM, интеграции и безопасность.

Полезные советы и типичные ошибки новичков

Советы

  1. Всегда работай в /local/. Шаблоны, компоненты, модули — только там.
  2. D7 и неймспейсы. Пиши новый код на D7, соблюдай PSR-12, используй строгие типы.
  3. Кэш-политика. На чтении — кэшируй, на изменении — инвалидируй теги. Не кэшируй персональные данные без ключей пользователя.
  4. Безопасность. XSS — через htmlspecialcharsbx, CSRF — через фильтр ActionFilter\Csrf, проверяй права (\Bitrix\Main\Engine\CurrentUser).
  5. Производительность. Меньше запросов к БД, индексы по фильтрам, не трогай SELECT *. Включи опкеш, профилируй «Монитором производительности».
  6. Миграции. Держи структуру (инфоблоки, HL-блоки, типы почтовых событий) в коде. Без ручных кликов на проде.
  7. Git и ревью. Короткие PR/коммиты, код-ревью, читайте диффы.
  8. CI/CD. Автосборка, деплой без «запрыгивания на прод».
  9. Логи и мониторинг. \Bitrix\Main\Diag\Debug::writeToFile на dev, централизованный сбор логов на prod.
  10. Учись читать ядро. Много ответов — в исходниках модулей.

Ошибки

  • Патчить файлы в /bitrix/ → потеряешь на обновлении.
  • Смешивать верстку и бизнес-логику в шаблоне → расширяй компонент.
  • Делать 20 запросов в цикле по элементам → собери ID, сделай один батч.
  • Отсутствие кэша или невалидируемый кэш → перегенерируй по тегам.
  • Хардкодить пути/ID → выноси в параметры/константы/настройки.
  • Игнорировать обработку ошибок/исключений → заваливаешь страницу вместо graceful-fail.

Дополнительно: примеры, которые пригодятся каждый день

Мини-миграция создания HL-блока (внутри модуля/скрипта установки)


use Bitrix\Highloadblock\HighloadBlockTable;
$addRes = HighloadBlockTable::add([
  'NAME'       => 'BookLikes',
  'TABLE_NAME' => 'b_hl_book_likes',
]);
$hlId = (int)$addRes->getId();
// Добавь пользовательские поля UF_ITEM_ID, UF_USER_ID через CUserTypeEntity::Add
    

Проверка прав доступа (например, только для редакторов)


use Bitrix\Main\Engine\CurrentUser;
$current = CurrentUser::get();
if (!$current->isAdmin() && !$current->canDoOperation('edit_other_settings')) {
  throw new \Bitrix\Main\AccessDeniedException('Недостаточно прав');
}
    

Ручной AJAX с Fetch + CSRF


fetch('/local/ajax/like.php', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ id: 123, sessid: BX.bitrix_sessid() })
}).then(r => r.json()).then(console.log);
    

Транзакция в D7


$connection = \Bitrix\Main\Application::getConnection();
$connection->startTransaction();
try {
  // ... твои DML-операции
  $connection->commitTransaction();
} catch (\Throwable $e) {
  $connection->rollbackTransaction();
  throw $e;
}
    

Дорожная карта на 90 дней

  • Недели 1–2: HTML/CSS/JS база, современный PHP 8, Git. Подними локальное окружение (Docker).
  • Недели 3–4: Введение в Bitrix: структура проекта, инфоблоки/HL-блоки, настройка шаблона.
  • Недели 5–6: Свой компонент: фильтр, пагинация, кэш. JS-интерактив (AJAX-action).
  • Недели 7–8: ORM, события, tagged cache, оптимизация запросов, безопасность.
  • Недели 9–10: Миграции, простая интеграция (например, веб-хуки/платёжка).
  • Недели 11–12: Проект для портфолио, ревью кода, подготовка к сертификации.

Итог

Стать разработчиком на 1С-Битрикс — это не про «магические галочки в админке», а про инженерный подход: чистый код, D7-ядро, кэш и безопасность, миграции и автоматизация. Начни с малого — собери свой компонент, добавь фильтр и лайки, заверни всё в кэш, подружись с ORM и событиями. Через пару месяцев уверенной практики ты сможешь брать реальные задачи и расти до мидла, а дальше — специализироваться на e-commerce, интеграциях или высоконагруженных проектах.

Теги: 1С-Битрикс, разработчик Битрикс, веб-разработка, PHP, JavaScript, ORM, кэш, компоненты, инфоблоки, highload-блоки, портфолио, сертификация, Docker, Git, CI/CD


Валерий Макеев
26.10.2025 15:03
Код безопасно создаёт инфоблок типа «Каталог» с кодом books_catalog и привязкой к сайту s1, только если такого инфоблока ещё нет — идеально подходит для автоматизированных развёртываний и миграций.
Код
<?php
// Создаёт инфоблок "Книги" в корне сайта, если он ещё не существует
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();

use Bitrix\Main\Loader;
use Bitrix\Iblock\IblockTable;
use Bitrix\Iblock\TypeTable;

Loader::includeModule('iblock');

$iblockCode = 'books_catalog';
$siteId = 's1'; // замени на актуальный ID сайта

// Проверяем, существует ли уже такой инфоблок
$existing = IblockTable::getList([
    'filter' => ['=CODE' => $iblockCode, '=LID' => $siteId],
    'limit' => 1
])->fetch();

if ($existing) {
    echo "Инфоблок «Книги» уже существует (ID: {$existing['ID']})\n";
    return;
}

// Убеждаемся, что тип инфоблоков "catalog" существует
$iblockType = TypeTable::getList([
    'filter' => ['=ID' => 'catalog'],
    'limit' => 1
])->fetch();

if (!$iblockType) {
    throw new \Exception('Тип инфоблоков "catalog" не найден. Убедитесь, что установлен модуль "Каталог".');
}

// Создаём инфоблок
$result = IblockTable::add([
    'ACTIVE' => 'Y',
    'NAME' => 'Книги',
    'CODE' => $iblockCode,
    'IBLOCK_TYPE_ID' => 'catalog',
    'LID' => [$siteId],
    'SORT' => 500,
    'GROUP_ID' => [
        2 => 'R', // чтение для всех
        1 => 'X', // полный доступ админам
    ],
    'VERSION' => 2,
]);

if ($result->isSuccess()) {
    echo "Инфоблок «Книги» успешно создан (ID: {$result->getId()})\n";
} else {
    echo "Ошибка создания инфоблока: " . implode(', ', $result->getErrorMessages()) . "\n";
}

Стоимость услуг по разработке и сопровождению сайтов на 1C-Битрикс

Техническая поддержка

сайтов на CMS 1C-Битрикс

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

* стоимость зависит от объема и сложности выполняемых работ

Участие в проекте

привлечение в проект на part-time основе

от 30 000 рублей / неделя

Возможно участие в проекте на ежедневной основе, как разработчика. Занятость - до 20 часов в неделю
Минимальный срок - одна неделя.

* сумма фиксированная

Перенос сайтов на «1С-Битрикс»

сайты на платформе «1С-Битрикс» — это удобство, надежность и высокая посещаемость

от 12 000 рублей
Перенос сайтов с любых CMS и статичных страниц на платформу «1С-Битрикс», с учетом дизайна, верстки и урл-адресов. С сохранением всей информации и структуры сайта.

* зависит от объема выполняемых работ.