Розробка дошки оголошень на 1С-Бітрікс

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Розробка дошки оголошень на 1С-Бітрікс
Середня
~1-2 тижні
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Розробка дошки оголошень на 1С-Bitrix

Дошка оголошень — складніша, ніж здається на перший погляд. Це не просто «список товарів». Користувачі самі розміщують оголошення, модератори перевіряють контент, потрібен пошук з фільтрами за багатьма параметрами, управління статусами та термінами оголошень, платне просування, особистий кабінет продавця. Bitrix дає хорошу базу — інфоблоки, модуль користувачів, фасетний пошук — але конкретну логіку дошки потрібно будувати поверх.

Структура інфоблоку оголошень

Інфоблок — основне сховище. Символьний код: classifieds. Тип: ADS.

Обов'язкові властивості інфоблоку:

Властивість Код Тип
Ціна PRICE Число
Тип угоди DEAL_TYPE Список (Продам/Куплю/Обміняю/Віддам)
Місто CITY Довідник (HL-блок)
Телефон продавця PHONE Рядок
Статус AD_STATUS Список (Активне/Модерація/Відхилено/Прострочено)
Дата закінчення EXPIRE_DATE Дата
Перегляди VIEW_COUNT Число
VIP IS_VIP Прапор
Користувач USER_ID Число (FK на b_user)
Фотографії PHOTOS Файл (множинне)

Розділ інфоблоку — категорія оголошень (Транспорт, Нерухомість, Електроніка тощо). Ієрархія розділів — дерево через b_iblock_section.

Розміщення оголошення користувачем

Форма додавання оголошення — сторінка в /ads/add/. Ключовий момент: користувач завантажує контент, значить потрібен захист від спаму та обов'язкова модерація.

// /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() з фільтром. Для навантаженого проєкту — фасетний пошук Bitrix (модуль search) або інтеграція з ElasticSearch.

Приклад фільтра з діапазоном цін:

$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.

Закінчення терміну оголошень

Агент перевіряє прострочені оголошення:

// Реєстрація агента в /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();';
    }
}

Особистий кабінет користувача

Сторінка /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, щоб не сповільнювати початковий рендер і не рахувати ботів:

// /local/ajax/ad_view.php
$adId = (int)$_POST['ad_id'];
if ($adId > 0) {
    $current = (int)\CIBlockElement::GetProperty(CLASSIFIEDS_IBLOCK_ID, $adId, [], ['CODE' => 'VIEW_COUNT'])->GetNext()['VALUE'];
    \CIBlockElement::SetPropertyValues($adId, CLASSIFIEDS_IBLOCK_ID, $current + 1, 'VIEW_COUNT');
}

Терміни розробки

Варіант Склад Термін
Базова дошка Інфоблок, розміщення, список, фільтр 8–12 днів
З модерацією і ОК + Модерація, особистий кабінет, агент закінчення 12–18 днів
Повнофункціональна + VIP-оголошення, пошук, сповіщення, статистика 20–30 днів