1. Измените ID инфоблока
В коде найдите const IBLOCK_ID = 17; и замените 17 на реальный ID вашего каталога.
2. Режим DRY_RUN (опционально)Перед первым запуском установите const DRY_RUN = true;
, чтобы скрипт только вывел, что он будет делать, но не менял БД. Запустите вручную через командную строку и проверьте логи.
3. Настройка cron (примеры)Через командную строку (php-cli):bash
(каталоги нужно указать ваши)
# Запускать каждый час
0 * * * * /usr/bin/php -f /home/bitrix/www/bitrix/php_interface/cron/section_picture_filler.php >> /home/bitrix/www/upload/cron_section_images.log 2>&1
# Или через wget (если нет доступа к cli)
0 * * * * wget -q -O /dev/null "[URL=https://ваш-сайт.ру/bitrix/php_interface/cron/section_picture_filler.php"]https://ваш-сайт.ру/bitrix/php_interface/cron/section_picture_filler.php"[/URL];
4. Права на файл
Убедитесь, что скрипт доступен для выполнения (chmod +x для cli-версии). При запуске через веб (не рекомендуется, но можно) - защитите файл от прямого доступа проверкой на php_sapi_name() == 'cli'.
[CODE]/*** Скрипт для автоматического заполнения картинок разделов каталога
* Запуск по cron: каждые N минут/часов
*/
$_SERVER['DOCUMENT_ROOT'] = dirname(__DIR__, 3); // поднимаемся на уровень выше /bitrix
define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS', true);
define('NO_AGENT_CHECK', true);
define('BX_BUFFER_USED', false);
define('BX_NO_ACCELERATOR_RESET', true);
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';
use Bitrix\Main\Loader;
use Bitrix\Iblock\SectionTable;
use Bitrix\Iblock\ElementTable;
class SectionPictureFillerCron
{
/**
* ID инфоблока (каталога) — обязательно замените на свой
*/
const IBLOCK_ID = 17;
/**
* Режим "только сухие проверки" (dry-run)
* true - только вывод, что будет сделано, без обновлений БД
*/
const DRY_RUN = false;
/**
* Лимит на количество разделов за один запуск.
* 0 = без лимита.
*/
const LIMIT = 0;
/**
* Точка входа
*/
public static function run()
{
if (!Loader::includeModule('iblock')) {
self::log("Ошибка: модуль iblock не загружен");
return;
}
$startTime = microtime(true);
self::log("=== Запуск заполнения картинок разделов ===");
self::log("Инфоблок ID: " . self::IBLOCK_ID . (self::DRY_RUN ? " (DRY-RUN режим)" : ""));
$sections = self::getSectionsWithoutPicture();
$total = count($sections);
self::log("Найдено разделов без картинки: $total");
if (self::LIMIT > 0 && $total > self::LIMIT) {
$sections = array_slice($sections, 0, self::LIMIT);
self::log("Обработано будет только " . self::LIMIT . " разделов за этот запуск");
}
$updated = 0;
$skipped = 0;
$errors = 0;
foreach ($sections as $section) {
$sectionId = $section['ID'];
$iblockId = $section['IBLOCK_ID'];
$productPictureId = self::getFirstProductPictureId($sectionId, $iblockId);
if (!$productPictureId) {
self::log("Раздел [ID: $sectionId] — нет товаров с картинками");
$skipped++;
continue;
}
if (self::DRY_RUN) {
self::log("[DRY-RUN] Разделу [ID: $sectionId] будет назначена картинка ID: $productPictureId");
$updated++;
continue;
}
$fileArray = \CFile::MakeFileArray($productPictureId);
if (!$fileArray) {
self::log("Ошибка: не удалось создать массив файла для картинки ID $productPictureId (раздел $sectionId)");
$errors++;
continue;
}
$sectionUpdater = new \CIBlockSection();
if ($sectionUpdater->Update($sectionId, ['PICTURE' => $fileArray])) {
self::log("✓ Разделу [ID: $sectionId] назначена картинка ID: $productPictureId");
$updated++;
} else {
self::log("✗ Ошибка обновления раздела $sectionId: " . $sectionUpdater->LAST_ERROR);
$errors++;
}
}
$time = round(microtime(true) - $startTime, 2);
self::log("=== Готово. Обновлено: $updated, пропущено: $skipped, ошибок: $errors. Время: {$time} с ===");
}
/**
* Возвращает ID разделов, у которых нет установленной картинки (PICTURE)
*/
private static function getSectionsWithoutPicture()
{
$params = [
'select' => ['ID', 'IBLOCK_ID'],
'filter' => [
'=IBLOCK_ID' => self::IBLOCK_ID,
'=PICTURE' => false,
],
'order' => ['LEFT_MARGIN' => 'ASC'],
];
$result = SectionTable::getList($params);
$sections = [];
while ($row = $result->fetch()) {
$sections[] = $row;
}
return $sections;
}
/**
* Ищет ID картинки (PREVIEW_PICTURE или DETAIL_PICTURE) первого активного товара в разделе и его подразделах
*/
private static function getFirstProductPictureId($sectionId, $iblockId)
{
$result = ElementTable::getList([
'select' => ['ID', 'PREVIEW_PICTURE', 'DETAIL_PICTURE'],
'filter' => [
'=IBLOCK_ID' => $iblockId,
'=ACTIVE' => 'Y',
'=SECTION_ID' => $sectionId,
'INCLUDE_SUBSECTIONS' => 'Y',
],
'order' => ['SORT' => 'ASC', 'ID' => 'ASC'],
'limit' => 100,
]);
while ($element = $result->fetch()) {
$pictureId = (int)($element['PREVIEW_PICTURE'] ?: $element['DETAIL_PICTURE']);
if ($pictureId > 0) {
return $pictureId;
}
}
return null;
}
/**
* Логирование в файл
*/
private static function log($message)
{
$logEntry = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
$logFile = $_SERVER['DOCUMENT_ROOT'] . '/upload/section_picture_filler.log';
file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
}
}
// Запуск
SectionPictureFillerCron::run();
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_after.php';[/CODE]