Розробка дошки оголошень на 1С-Бітрікс
Дошка оголошень — не просто «список товарів». Користувачі самі створюють контент, потрібна модерація, гнучкий пошук з фільтрами, керування статусами та термінами. Без готового рішення доводиться будувати цю логіку з нуля. Ми вже реалізували такі проєкти, тому знаємо типові граблі: наприклад, уповільнення пошуку при 50 000 оголошеннях або проблеми з кешуванням при великій кількості VIP-оголошень. Вартість виправлення таких помилок може бути співставна з початковою розробкою, тому важливо закласти правильну архітектуру з першого дня. Неправильне проєктування може обійтися в сотні тисяч гривень, тому ми рекомендуємо ретельно підходити до вибору технологій.
Наш підхід — використовувати інфоблоки, HL-блоки, компоненти 2.0 та теговане кешування. Згідно з офіційною документацією, компонент 2.0 дозволяє кешувати окремі частини шаблону, що критично для продуктивності. У цій статті розберемо ключові блоки дошки: від структури даних до агента закінчення терміну. Якщо ви плануєте запустити дошку оголошень — отримайте консультацію: ми підготуємо ТЗ і розрахуємо терміни.
Як влаштована структура інфоблоку оголошень?
Інфоблок — основне сховище. Символьний код: classifieds. Тип: ADS. Обов'язкові властивості:
| Властивість | Код | Тип |
|---|---|---|
| Ціна | PRICE |
Число |
| Тип угоди | DEAL_TYPE |
Список (Продам/Куплю/Обміняю/Віддам) |
| Місто | CITY |
Довідник (HL-блок) |
| Телефон продавця | PHONE |
Рядок |
| Статус | AD_STATUS |
Список (Активно/Модерація/Відхилено/Закінчився) |
| Дата закінчення | EXPIRE_DATE |
Дата |
| Перегляди | VIEW_COUNT |
Число |
| VIP | IS_VIP |
Прапорець |
| Користувач | USER_ID |
Число (FK на b_user) |
| Фотографії | PHOTOS |
Файл (множинне) |
| Дата створення | DATE_CREATE |
Дата (автоматично) |
Розділ інфоблоку — категорія оголошень (Транспорт, Нерухомість тощо). Ієрархія розділів — дерево через b_iblock_section. Така структура забезпечує швидкий пошук і фільтрацію за категоріями.
Розміщення оголошення користувачем: покрокова інструкція
Форма додавання оголошення — сторінка /ads/add/. Процес складається з кількох кроків:
- Авторизація: якщо користувач не авторизований, його перенаправляє на
/auth/. - Заповнення форми: користувач вводить назву, опис, ціну, категорію, завантажує фотографії.
- Валідація: перевірка обов'язкових полів, формату телефону, розмірів зображень.
- Відправка на модерацію: оголошення зберігається з прапорцем
ACTIVE='N'та статусомMODERATION. Модератори отримують сповіщення. - Підтвердження: після успішного збереження користувач бачить повідомлення про успіх.
Ключовий момент: користувач завантажує контент — потрібен захист від спаму та обов'язкова модерація.
// /local/components/local/ads.add/class.php
namespace Local\Ads;
class AdsAddComponent extends \CBitrixComponent
{
public function executeComponent(): void
{
if (!$GLOBALS['USER']->IsAuthorized()) {
LocalRedirect('/auth/?backurl=/ads/add/');
return;
}
if ($this->request->isPost() && check_bitrix_sessid()) {
$this->addAd();
}
$this->includeComponentTemplate();
}
private function addAd(): void
{
$el = new \CIBlockElement();
// Обработка загруженных фотографий
$photos = [];
if (!empty($_FILES['PHOTOS']['tmp_name'])) {
foreach ($_FILES['PHOTOS']['tmp_name'] as $i => $tmpName) {
if (is_uploaded_file($tmpName)) {
$photos[] = [
'name' => $_FILES['PHOTOS']['name'][$i],
'size' => $_FILES['PHOTOS']['size'][$i],
'tmp_name' => $tmpName,
'type' => $_FILES['PHOTOS']['type'][$i],
];
}
}
}
$adId = $el->Add([
'IBLOCK_ID' => CLASSIFIEDS_IBLOCK_ID,
'NAME' => htmlspecialchars($this->request->getPost('title')),
'DETAIL_TEXT' => htmlspecialchars($this->request->getPost('description')),
'IBLOCK_SECTION_ID' => (int)$this->request->getPost('category_id'),
'ACTIVE' => 'N', // Изначально неактивно, до модерации
'PROPERTY_VALUES' => [
'PRICE' => (float)$this->request->getPost('price'),
'DEAL_TYPE' => $this->request->getPost('deal_type'),
'PHONE' => htmlspecialchars($this->request->getPost('phone')),
'USER_ID' => $GLOBALS['USER']->GetID(),
'AD_STATUS' => 'MODERATION',
'EXPIRE_DATE' => date('d.m.Y', strtotime('+30 days')),
'VIEW_COUNT' => 0,
'PHOTOS' => $photos,
],
]);
if ($adId) {
$this->arResult['SUCCESS'] = true;
$this->arResult['AD_ID'] = $adId;
// Уведомить модераторов
$this->notifyModerators($adId);
} else {
$this->arResult['ERROR'] = $el->LAST_ERROR;
}
}
}
Як працює модерація оголошень?
Сторінка модератора — стандартний список елементів інфоблоку з фільтром за AD_STATUS = MODERATION. Дії модератора змінюють статус і активність:
// Одобрить объявление
$el = new \CIBlockElement();
$el->Update($adId, ['ACTIVE' => 'Y']);
\CIBlockElement::SetPropertyValues($adId, CLASSIFIEDS_IBLOCK_ID, 'ACTIVE', 'AD_STATUS');
// Отклонить с причиной
\CIBlockElement::SetPropertyValues($adId, CLASSIFIEDS_IBLOCK_ID, [
'AD_STATUS' => 'REJECTED',
'REJECT_REASON' => $reason,
]);
$el->Update($adId, ['ACTIVE' => 'N']);
// Уведомить пользователя
$event = new \Bitrix\Main\Mail\Event([
'EVENT_NAME' => 'AD_MODERATION_RESULT',
'LID' => SITE_ID,
'C_FIELDS' => [
'AD_ID' => $adId,
'STATUS' => $status,
'REASON' => $reason,
],
]);
$event->send();
Модератор може також відредагувати оголошення, змінити ціну або категорію. Всі дії логуються.
Пошук і фільтрація
Фільтр оголошень — критична частина UX. Для простого пошуку — стандартний CIBlockElement::GetList() з фільтром. Для навантаженого проєкту (понад 100 000 оголошень) — фасетний пошук Бітрікс (модуль search) або інтеграція з ElasticSearch. На одному з проєктів з каталогом у 200 000 оголошень ми оптимізували пошук, замінивши стандартний GetList на фасетний пошук, що зменшило час відгуку з 5с до 0.8с. Фасетний пошук працює в 3–5 разів швидше стандартного при складних фільтрах.
Приклад фільтра з діапазоном цін:
$filter = [
'IBLOCK_ID' => CLASSIFIEDS_IBLOCK_ID,
'ACTIVE' => 'Y',
'SECTION_ID' => $categoryId,
'>PROPERTY_PRICE' => $priceMin,
'<PROPERTY_PRICE' => $priceMax,
'PROPERTY_CITY' => $cityId,
'PROPERTY_AD_STATUS' => 'ACTIVE',
];
$sort = ['PROPERTY_IS_VIP' => 'DESC', 'DATE_ACTIVE_FROM' => 'DESC'];
VIP-оголошення завжди зверху через сортування за прапорцем IS_VIP DESC. При 500 000 оголошеннях ми рекомендуємо використовувати пошуковий індекс з інкрементальним оновленням.
Закінчення терміну оголошень
Агент перевіряє прострочені оголошення раз на добу. Реєстрація агента та метод обробки:
// Регистрация агента в /local/php_interface/init.php
\CAgent::AddAgent(
'Local\\Ads\\ExpireAgent::run();',
'local.ads',
'N',
86400, // Раз в сутки
);
// Метод агента
class ExpireAgent
{
public static function run(): string
{
$today = date('d.m.Y');
$result = \CIBlockElement::GetList(
[],
[
'IBLOCK_ID' => CLASSIFIEDS_IBLOCK_ID,
'ACTIVE' => 'Y',
'<PROPERTY_EXPIRE_DATE' => $today,
],
false,
false,
['ID', 'PROPERTY_USER_ID']
);
while ($ad = $result->Fetch()) {
$el = new \CIBlockElement();
$el->Update($ad['ID'], ['ACTIVE' => 'N']);
\CIBlockElement::SetPropertyValues($ad['ID'], CLASSIFIEDS_IBLOCK_ID, 'EXPIRED', 'AD_STATUS');
// Уведомить пользователя
}
return 'Local\\Ads\\ExpireAgent::run();';
}
}
Для каталогу в 1 000 000 оголошень агент може виконуватись довше 5 хвилин. У таких випадках ми запускаємо агент частинами по 1000 записів і використовуємо блокування.
Особистий кабінет користувача
Сторінка /personal/ads/ — список оголошень поточного користувача:
$myAds = \CIBlockElement::GetList(
['DATE_CREATE' => 'DESC'],
[
'IBLOCK_ID' => CLASSIFIEDS_IBLOCK_ID,
'PROPERTY_USER_ID' => $GLOBALS['USER']->GetID(),
],
false,
['nPageSize' => 20],
['ID', 'NAME', 'ACTIVE', 'PROPERTY_AD_STATUS', 'PROPERTY_EXPIRE_DATE', 'PROPERTY_VIEW_COUNT']
);
Дії користувача: редагувати, деактивувати, продовжити термін (якщо оголошення закінчилось), видалити. Також відображається статистика переглядів і контактів.
Лічильник переглядів
При кожному відкритті детальної сторінки — інкрементувати лічильник. Через AJAX, щоб не сповільнювати початковий рендер і не рахувати ботів: відправляємо POST-запит з ad_id, отримуємо поточне значення через CIBlockElement::GetProperty, оновлюємо PROPERTY_VIEW_COUNT. Для високонавантажених проєктів (понад 10 000 переглядів на годину) рекомендуємо асинхронну чергу або Redis, щоб не блокувати запис на кожному перегляді.
Що входить у роботу?
При замовленні дошки оголошень під ключ ми надаємо:
- детальне технічне завдання з прототипом;
- налаштування інфоблоків, HL-блоків та агентів;
- розробку кастомних компонентів та AJAX-обробників;
- інтеграцію з платіжними системами та сервісами доставки (СДЕК, Нова Пошта);
- документацію та навчання персоналу;
- 2 тижні гарантійної підтримки після запуску.
Терміни розробки
| Варіант | Склад | Термін |
|---|---|---|
| Базова дошка | Інфоблок, розміщення, список, фільтр | 8–12 днів |
| З модерацією та ОК | + Модерація, особистий кабінет, агент закінчення | 12–18 днів |
| Повнофункціональна | + VIP-оголошення, пошук, сповіщення, статистика | 20–30 днів |
Зв'яжіться з нами, щоб отримати консультацію та точну оцінку вашого проєкту. Наші інженери мають 5+ років досвіду в розробці на 1С-Бітрікс та гарантують безпеку даних. Замовте розробку дошки оголошень, яка буде стабільно працювати під навантаженням та приносити прибуток.







