Bitrix — мощная корпоративная CMS-платформа, популярная в России и Восточной Европе для создания корпоративных сайтов, e-commerce-платформ и intranet-решений. Хотя порог входа высок, освоение разработки под Bitrix открывает доступ к корпоративным проектам со сложными требованиями. В этом руководстве рассматриваются ключевые паттерны разработки под Bitrix с точки зрения senior-разработчика.
Почему Bitrix
Bitrix предлагает убедительные возможности для корпоративной среды:
- Платформа «всё в одном»: CMS, CRM, e-commerce в одной системе
- Информационные блоки: гибкая структура управления контентом
- Встроенные модули: форумы, блоги, e-commerce, workflows
- Корпоративные возможности: кластеризация, кеширование, поддержка мультисайтовости
- Российский рынок: доминирующая CMS в российском корпоративном сегменте
Понимание информационных блоков (Infoblocks)
Infoblocks — ключевая структура данных Bitrix: воспринимайте их как настраиваемые типы контента со свойствами, разделами и элементами.
Обзор структуры
Infoblock Type
└── Infoblock
├── Sections (categories)
└── Elements (content items)
└── Properties (custom fields)
Работа с Infoblocks через API
<?php
// Подключить ядро Bitrix
require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");
// Загрузить модуль iblock
CModule::IncludeModule("iblock");
// Получить элементы из infoblock
$arFilter = array(
"IBLOCK_ID" => 5,
"ACTIVE" => "Y",
"SECTION_ID" => 10
);
$arSelect = array(
"ID",
"NAME",
"DETAIL_TEXT",
"PROPERTY_PRICE",
"PROPERTY_BRAND"
);
$res = CIBlockElement::GetList(
array("SORT" => "ASC"), // Сортировка
$arFilter, // Фильтр
false, // Группировка
false, // Навигация
$arSelect // Выбор полей
);
while ($element = $res->GetNextElement()) {
$fields = $element->GetFields();
$props = $element->GetProperties();
echo $fields["NAME"] . ": " . $props["PRICE"]["VALUE"] . "<br>";
}
?>
Создание элементов Infoblock
<?php
CModule::IncludeModule("iblock");
$element = new CIBlockElement;
$arFields = array(
"IBLOCK_ID" => 5,
"IBLOCK_SECTION_ID" => 10,
"NAME" => "New Product",
"ACTIVE" => "Y",
"PREVIEW_TEXT" => "Short description",
"DETAIL_TEXT" => "Full product description",
"PROPERTY_VALUES" => array(
"PRICE" => 1999,
"BRAND" => "Samsung",
"FEATURES" => array("Feature 1", "Feature 2")
)
);
if ($elementId = $element->Add($arFields)) {
echo "Element created with ID: " . $elementId;
} else {
echo "Error: " . $element->LAST_ERROR;
}
?>
Копирование свойств и форм Infoblock
Когда у вас есть несколько infoblocks одного типа и нужно скопировать конфигурации форм:
<?php
require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/bx_root.php");
require_once($_SERVER["DOCUMENT_ROOT"] . BX_PERSONAL_ROOT . "/modules/main/include/prolog_before.php");
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
CModule::IncludeModule("iblock");
if (intval($_REQUEST["IBLOCK_ID_FORMS"]) > 0 && !empty($_REQUEST["IBLOCK_TYPE_ID"])) {
$masterIblockId = intval($_REQUEST["IBLOCK_ID_FORMS"]);
$iblockTypeId = $_REQUEST["IBLOCK_TYPE_ID"];
// Получить свойства master infoblock
$masterProperties = array();
$dbProperties = CIBlockProperty::GetList(
array("sort" => "asc", "name" => "asc"),
array("ACTIVE" => "Y", "IBLOCK_ID" => $masterIblockId)
);
while ($property = $dbProperties->GetNext()) {
$masterProperties[$property['CODE']] = 'PROPERTY_' . $property['ID'];
}
// Настройки для копирования
$settings = array(
array('name' => 'form_element_#ID#', 'group' => 'form'),
array('name' => 'form_section_#ID#', 'group' => 'form'),
array('name' => 'tbl_iblock_list_#MD5#', 'group' => 'list'),
array('name' => 'tbl_iblock_element_#MD5#', 'group' => 'list'),
);
// Получить настройки из master
foreach ($settings as $key => $value) {
$name = str_replace(
array('#ID#', '#MD5#'),
array($masterIblockId, md5($iblockTypeId . "." . $masterIblockId)),
$value['name']
);
$settings[$key]['value'] = CUserOptions::GetOption($value['group'], $name);
}
// Применить ко всем infoblocks того же типа
$dbResult = CIBlock::GetList(
array(),
array('=TYPE' => $iblockTypeId, '!ID' => $masterIblockId),
true
);
while ($iblock = $dbResult->Fetch()) {
// Сопоставить ID свойств
$search = array();
$replacement = array();
$dbProps = CIBlockProperty::GetList(
array("sort" => "asc"),
array("ACTIVE" => "Y", "IBLOCK_ID" => $iblock['ID'])
);
while ($prop = $dbProps->GetNext()) {
if (!empty($masterProperties[$prop['CODE']])) {
$search[] = $masterProperties[$prop['CODE']];
$replacement[] = 'PROPERTY_' . $prop['ID'];
}
}
// Скопировать настройки с сопоставлением свойств
foreach ($settings as $value) {
$name = str_replace(
array('#ID#', '#MD5#'),
array($iblock['ID'], md5($iblock['IBLOCK_TYPE_ID'] . "." . $iblock['ID'])),
$value['name']
);
$newValue = array();
foreach ($value['value'] as $k => $string) {
$newValue[$k] = str_replace($search, $replacement, $string);
}
CUserOptions::DeleteOption($value['group'], $name);
CUserOptions::SetOption($value['group'], $name, $newValue, true);
}
}
echo "Forms copied successfully!";
}
?>
Администрирование форума
Bitrix включает встроенный модуль форума. Ниже показано, как управлять содержимым форума программно.
Удаление всех сообщений пользователя
Полезно для удаления спама:
<?php
// Конфигурация
$badUserId = 29541;
// Удалить сообщения пользователя
$deleteMessages = "DELETE FROM b_forum_message WHERE author_id = $badUserId";
// Обновить метаданные темы после удаления
$updateTopics = "UPDATE b_forum_topic as t
LEFT JOIN (
SELECT
MAX(gm.id) as id,
gm.topic_id,
MAX(gm.post_date) as post_date
FROM b_forum_message as gm
GROUP BY topic_id
) as g ON t.id = g.topic_id
LEFT JOIN b_forum_message as m ON m.id = g.id
SET
t.last_message_id = g.id,
t.last_poster_id = m.author_id,
t.last_poster_name = m.author_name,
t.last_post_date = g.post_date,
t.abs_last_message_id = g.id,
t.abs_last_poster_id = m.author_id,
t.abs_last_poster_name = m.author_name,
t.abs_last_post_date = g.post_date
WHERE t.abs_last_message_id <> g.id";
// Подключиться, используя конфигурацию Bitrix
include $_SERVER["DOCUMENT_ROOT"] . '/bitrix/php_interface/dbconn.php';
$db = mysqli_connect($DBHost, $DBLogin, $DBPassword, $DBName);
mysqli_set_charset($db, 'utf8');
mysqli_query($db, $deleteMessages);
mysqli_query($db, $updateTopics);
echo "Spam removed and topics updated.";
?>
Разработка компонентов
Bitrix использует компоненты для повторно используемой функциональности.
Базовая структура компонента
/local/components/mycompany/mycomponent/
├── .description.php # Метаданные компонента
├── .parameters.php # Определение входных параметров
├── component.php # Основная логика
├── class.php # ООП-класс компонента
└── templates/
└── .default/
├── template.php
├── style.css
└── script.js
Пример класса компонента
<?php
// /local/components/mycompany/product.list/class.php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
use Bitrix\Main\Loader;
class ProductListComponent extends CBitrixComponent
{
protected function checkModules()
{
if (!Loader::includeModule('iblock')) {
throw new \Exception('Module iblock not installed');
}
}
protected function getProducts()
{
$products = array();
$filter = array(
"IBLOCK_ID" => $this->arParams["IBLOCK_ID"],
"ACTIVE" => "Y"
);
if (!empty($this->arParams["SECTION_ID"])) {
$filter["SECTION_ID"] = $this->arParams["SECTION_ID"];
}
$res = \CIBlockElement::GetList(
array("SORT" => "ASC"),
$filter,
false,
array("nPageSize" => $this->arParams["PAGE_SIZE"]),
array("ID", "NAME", "PREVIEW_PICTURE", "DETAIL_PAGE_URL")
);
while ($element = $res->GetNextElement()) {
$fields = $element->GetFields();
$fields["PROPERTIES"] = $element->GetProperties();
$products[] = $fields;
}
return $products;
}
public function executeComponent()
{
try {
$this->checkModules();
$this->arResult["PRODUCTS"] = $this->getProducts();
$this->includeComponentTemplate();
} catch (\Exception $e) {
ShowError($e->getMessage());
}
}
}
?>
D7 (современный API)
Bitrix D7 — современный API на основе ORM:
<?php
use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementTable;
Loader::includeModule('iblock');
// Запрос через D7
$elements = ElementTable::getList(array(
'select' => array('ID', 'NAME', 'IBLOCK_ID'),
'filter' => array(
'=IBLOCK_ID' => 5,
'=ACTIVE' => 'Y'
),
'order' => array('SORT' => 'ASC'),
'limit' => 10
));
while ($element = $elements->fetch()) {
echo $element['NAME'] . "<br>";
}
// Использование DataManager для пользовательских таблиц
use Bitrix\Main\Entity;
class MyCustomTable extends Entity\DataManager
{
public static function getTableName()
{
return 'my_custom_table';
}
public static function getMap()
{
return array(
'ID' => new Entity\IntegerField('ID', array(
'primary' => true,
'autocomplete' => true
)),
'NAME' => new Entity\StringField('NAME', array(
'required' => true
)),
'CREATED_AT' => new Entity\DatetimeField('CREATED_AT')
);
}
}
?>
Обработчики событий
Регистрируйте обработчики для событий Bitrix:
<?php
// /local/php_interface/init.php
AddEventHandler("iblock", "OnBeforeIBlockElementAdd", "MyOnBeforeElementAdd");
AddEventHandler("iblock", "OnAfterIBlockElementAdd", "MyOnAfterElementAdd");
function MyOnBeforeElementAdd(&$arFields)
{
// Проверить или изменить перед сохранением
if (empty($arFields["NAME"])) {
global $APPLICATION;
$APPLICATION->ThrowException("Name is required");
return false;
}
// Автоматически сгенерировать код из названия
$arFields["CODE"] = CUtil::translit(
$arFields["NAME"],
"ru",
array("replace_space" => "-", "replace_other" => "-")
);
return true;
}
function MyOnAfterElementAdd(&$arFields)
{
// Записать в лог или отправить уведомление после сохранения
CEventLog::Add(array(
"SEVERITY" => "INFO",
"AUDIT_TYPE_ID" => "IBLOCK_ELEMENT_ADD",
"MODULE_ID" => "iblock",
"ITEM_ID" => $arFields["ID"],
"DESCRIPTION" => "Element added: " . $arFields["NAME"]
));
}
?>
Кеширование
Bitrix предоставляет мощные механизмы кеширования:
<?php
$cacheTime = 3600; // 1 час
$cacheId = "my_cache_" . $IBLOCK_ID . "_" . $SECTION_ID;
$cachePath = "/my_component/";
$cache = new CPHPCache();
if ($cache->InitCache($cacheTime, $cacheId, $cachePath)) {
// Получить из кеша
$vars = $cache->GetVars();
$arResult = $vars["arResult"];
} elseif ($cache->StartDataCache()) {
// Сгенерировать данные
$arResult = getExpensiveData();
// Сохранить в кеш
$cache->EndDataCache(array("arResult" => $arResult));
}
?>
Ключевые выводы
- Изучите Infoblocks: основа управления контентом в Bitrix
- Используйте D7 API: современный подход на базе ORM
- Архитектура компонентов: единицы повторно используемой функциональности
- Событийная модель: расширяйте поведение через handlers
- Агрессивно используйте кеш: критично для производительности
- Знание базы данных: иногда необходим прямой SQL
У Bitrix высокий порог входа, но вложения окупаются мощными корпоративными возможностями — освоив эти основы, вы будете уверенно справляться со сложными проектами на Bitrix.