Yandex Metrika
sanches.free 2 просмотра

Поваренная книга Битриксиста: SQL, CLI, автозагрузка и ограничения штатных компонентов

Зачем вообще «поваренная книга»

Сбор заметок о том, что в документации разбросано по разделам: прямые запросы к БД на фоне API инфоблоков, ручной запуск ядра, повторное использование кода, реалистичные ограничения стандартных компонентов и точечная доработка административного интерфейса. Текст переработан с опорой на идеи оригинальной подборки, без копирования формулировок источника.

Прямые запросы к MySQL и глобальный $DB

Помимо CIBlockElement, CIBlockSection и остальных обёрток инфоблоков вы всегда имеете объект БД через $DB (или статические обёртки D7 там, где проект уже на них сидит). Плюсы простого SQL: можно выжать миллисекунды там, где GetList() тянет лишние JOIN и постобработку, и выразить условия, которые в фильтре API описывать неудобно. Минусы жёсткие: нужно знать схему таблиц, не задеть целостность и помнить, что внутренности ядра при мажорных обновлениях теоретически могут сдвинуться.

Разовые правки по ТЗ вроде «проставить анонс всем элементам одного набора» или «перекидывание элементов между разделами» часто записывают одним UPDATE. Перед выполнением на бою сохраните снимок: отдельная таблица-копия или хотя бы выборочный бэкап строк.

// Пример: перепривязать элемент без раздела к конкретному разделу в инфоблоке warehouse
$DB->Query(
    "UPDATE b_iblock_element SET IBLOCK_SECTION_ID = 84 "
    . "WHERE IBLOCK_ID = 6 AND IBLOCK_SECTION_ID IS NULL"
);

После массовых правок полезно прогнать переиндексацию поиска и кеши, если затронуты поля, участвующие в выдаче.

Запуск ядра из командной строки

Агенты в Битрикс изначально «подвешены» на хиты. Для стабильности их переносят на cron. Параллельно полезно уметь поднять пролог в отдельном PHP-файле: так проще отлаживать тяжёлые задачи и не держать логику внутри визитов посетителей.

Минимальный каркас: задать $_SERVER['DOCUMENT_ROOT'], отключить лишнюю статистику и права (осознанно!), подключить prolog_before.php. Ниже — заготовка «обновлятора» с защитой от веб-доступа.

if (php_sapi_name() !== 'cli') {
    die('Run in CLI');
}

$targetIblockId = 19;
$projectRoot = '/var/www/example-site';

$_SERVER['DOCUMENT_ROOT'] = $projectRoot;
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];

define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS', true);

require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';

class DemoIblockJob
{
    private $db;

    public function __construct()
    {
        global $DB;
        $this->db = $DB;
    }

    private $iblockId = 0;

    public function setIblockId($id)
    {
        $this->iblockId = (int)$id;
    }

    public function run()
    {
        // точка входа для реальной логики
    }
}

$job = new DemoIblockJob();
$job->setIblockId($targetIblockId);
$job->run();

Повторное использование кода между проектами

Если в загашнике лежат десятки служебных скриптов, их часто переносят без глобального рефакторинга. Штатный приём — зарегистрировать автозагрузку своего класса рядом с точкой входа:

CModule::AddAutoloadClasses('', [
    'RemoteApiHelper' => '/local/lib/RemoteApiHelper.php',
]);

Дальше класс доступен так же, как если бы лежал в модуле. Для крупных кусков логики устойчивее оформлять собственный компонент или сервис в /local: так проще версионировать и не ломать зависимости при обновлении ядра. Паттерн «адаптер» хорошо ложится на обёртку над «сырым» PDO или mysqli, если хотите единообразно ходить в БД с двух сторон.

Когда штатного компонента мало

Формально новый компонент нужен, когда нет готового сценария. Но даже «старые» решения иногда упираются в стены API. У поиска bitrix:search.page классический набор жалоб — жёсткая сортировка (релевантность или дата, часто только в одну сторону) и смешение полей заголовка, текста и тегов без тонкой сепарации. У подписки subscribe.edit — многошаговость и тяжёлый UX для простой формы.

Это не призыв «пилить всё с нуля», а напоминание: на этапе оценки закладывайте кастомный поиск или отдельный сценарий подписки, если интерфейс из коробки не совпадает с ожиданиями редакции.

Точечные правки админки

Для элемента инфоблока можно повесить обработчик на сохранение и автоматически набивать символьный код из названия через транслит.

// Условный обработчик: если код пуст, сгенерировать из имени
if (strlen((string)($_POST['CODE'] ?? '')) === 0) {
    $_POST['CODE'] = CUtil::translit($_POST['NAME'] ?? '', 'ru', [
        'replace_space' => '-',
        'replace_other' => '-',
    ]);
}

Списочные столбцы в админке часто расширяются штатной «звёздочкой» справа от таблицы. Вычислимое поле «на лету», которого нет в БД, в типовых списках иногда приходится вшивать в модуль-жертву — это компромисс; перед правкой ядра фиксируйте патч и план отката.

Несколько разделов у одного элемента

Основная привязка хранится в поле раздела, но группы элементов задаются отдельно — это штатная возможность, просто её редко выносят в ТЗ на витрине. Получить все разделы элемента можно через API CIBlockElement::GetElementGroups(); детали смотрите в справке по методу для вашей версии продукта.

Фильтры и документация

Сложная логика в GetList() — нормальная тема для чтения раздела про фильтры в официальной справке. Полезный приём: поиск записи «без значения свойства» через $filter['PROPERTY_CODE'] = false; (актуальность модификаторов проверяйте на стенде). Операторы вроде !<> встречаются в примерах сообщества — перед продакшеном прогоните на копии данных.

Итог

Прямой SQL, CLI-обвязка, автозагрузка и кастомные компоненты — инструменты одного порядка: экономят время, если применять их с бэкапом, осознанными константами безопасности и пониманием, что ядро со временем обновляют.

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии