פיתוח לוח מודעות מותאם אישית על 1C-Bitrix
לוח מודעות הוא לא רק "רשימת מוצרים." משתמשים יוצרים תוכן, מה שמחייב ניהול מתינות, חיפוש גמיש עם מסננים, ניהול סטטוסים ותאריכי תפוגה. ללא פתרון מוכן, צריך לבנות את הלוגיקה הזו מאפס. כבר יישמנו פרויקטים כאלה, ולכן אנו מכירים את המלכודות האופייניות: לדוגמה, האטה בחיפוש ב-50,000 מודעות, או בעיות מטמון עם מספר גדול של מודעות VIP. עלות תיקון הטעויות האלה יכולה להיות דומה לפיתוח הראשוני, ולכן חשוב להניח את הארכיטקטורה הנכונה מהיום הראשון.
הגישה שלנו היא שימוש בבלוקי מידע (infoblocks), בלוקי HL, רכיבים 2.0 ומטמון מתויג. לפי התיעוד הרשמי, רכיב 2.0 מאפשר שמירת מטמון של חלקי תבנית בודדים, מה שחיוני לביצועים. במאמר זה, נפרק את הבלוקים המרכזיים של לוח מודעות: ממבנה הנתונים ועד לסוכן התפוגה.
כיצד בנוי מבנה בלוק המידע למודעות?
בלוק המידע הוא האחסון הראשי. קוד סימלי: classifieds. סוג: ADS. מאפיינים נדרשים:
| מאפיין | קוד | סוג |
|---|---|---|
| מחיר | PRICE |
מספר |
| סוג עסקה | DEAL_TYPE |
רשימה (מכירה/קנייה/החלפה/חינם) |
| עיר | CITY |
ספרייה (בלוק HL) |
| טלפון מוכר | PHONE |
מחרוזת |
| סטטוס | AD_STATUS |
רשימה (פעיל/במתינות/נדחה/פג תוקף) |
| תאריך תפוגה | EXPIRE_DATE |
תאריך |
| צפיות | VIEW_COUNT |
מספר |
| VIP | IS_VIP |
דגל |
| משתמש | USER_ID |
מספר (מפתח זר ל-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; } } } כיצד פועלת מתינות המודעות?
דף המנחה הוא רשימת אלמנטים סטנדרטית של בלוק מידע עם מסנן // /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; } } } . פעולות המנחה משנות סטטוס ופעילות:
// Одобрить объявление $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(); המנחה יכול גם לערוך את המודעה, לשנות מחיר או קטגוריה. כל הפעולות מתועדות.
חיפוש וסינון
סינון מודעות הוא חלק קריטי בחוויית המשתמש. לחיפושים פשוטים — AD_STATUS = MODERATION סטנדרטי עם מסנן. לפרויקטים עם תעבורה גבוהה (מעל 100,000 מודעות) — חיפוש פקטורי של Bitrix (מודול // Одобрить объявление $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(); ) או אינטגרציית ElasticSearch. חיפוש פקטורי מהיר פי 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 תמיד בראש לפי מיון CIBlockElement::GetList(). ב-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 רשומות ומשתמשים בנעילה.
אזור אישי למשתמש
דף search — רשימת המודעות של המשתמש הנוכחי:
$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 עם $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']; , קבלת ערך נוכחי דרך 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();'; } } . לפרויקטים עם תעבורה גבוהה (מעל 10,000 צפיות בשעה), אנו ממליצים על תור אסינכרוני או Redis כדי למנוע חסימת כתיבה בכל צפייה.
מה כלול בעבודה?
בהזמנת לוח מודעות סוהר, אנו מספקים:
- מפרט טכני מפורט עם אב טיפוס;
- הגדרת בלוק מידע, בלוק HL וסוכן;
- פיתוח רכיבים מותאמים אישית ומטפלי AJAX;
- אינטגרציה עם מערכות תשלום ושירותי משלוחים (CDEK, דואר רוסי);
- תיעוד והדרכת צוות;
- שבועיים של תמיכת אחריות לאחר ההשקה.
לוחות זמנים לפיתוח
| אפשרות | היקף | לוח זמנים |
|---|---|---|
| לוח בסיסי | בלוק מידע, פרסום, רשימה, מסנן | 8–12 ימים |
| עם מתינות ואזור אישי | + מתינות, אזור אישי, סוכן תפוגה | 12–18 ימים |
| מלא | + מודעות VIP, חיפוש, הודעות, סטטיסטיקות | 20–30 ימים |
צרו קשר לייעוץ והערכה מדויקת של הפרויקט שלכם. למהנדסים שלנו יש ניסיון של 5+ שנים בפיתוח 1C-Bitrix והם מבטיחים אבטחת מידע. הזמינו לוח מודעות שיפעל בצורה אמינה תחת עומס ויפיק רווח.







