כיצד לחסוך 90% מזמן המנהלים בפעולות המוניות ב-Bitrix
מנהל צריך לעדכן מחירים עבור 500 מוצרים — ידנית מדובר ב-4 שעות עבודה. רשימת Bitrix הסטנדרטית מספקת רק חמש פעולות: הפעלה, השבתה, מחיקה, שינוי סעיף, ייצוא. אין פעולות מותאמות אישית. אנו מיישמים פעולות המוניות שחוסכות עד 90% מהזמן: עדכוני מחירים, תוספות מחיר, עדכוני מאפיינים, סנכרון עם 1C ופלטפורמות מסחר.
הצוות שלנו מפתח ממשקי ניהול עבור Bitrix כבר למעלה מ-7 שנים. בתקופה זו השלמנו יותר מ-50 פרויקטים, כולל קטלוגים עם 100,000+ מוצרים. אילו תרחישים הם הנפוצים ביותר? שינויי מחירים המוניים (תוספת/הנחה), העתקת מאפיינים ממוצר אחד לאחר, יצירת שדות SEO, עדכון מלאי דרך קובץ או API. במאמר זה, נבחן כיצד להוסיף כפתור מותאם אישית לרשימת אלמנטים של בלוק מידע, לכתוב handler ב-PHP, ולהגן על הפעולה מפני CSRF ושגיאות. תקופת ההחזר עבור פעולה כזו היא מספר חודשים בשל האצה פי 10 של עבודת המנהלים.
כיצד להוסיף פעולה מותאמת אישית לתפריט ההקשר?
רשימת בלוק המידע הסטנדרטית נבנית על ידי רכיב bitrix:iblock.admin.element.list. כדי להוסיף כפתור חדש, אין צורך לערוך קבצי מערכת — השתמשו בהזרקת JavaScript או באירוע OnAdminListDisplay. הזרקת JavaScript מהירה פי 3 ליישום מאשר שינוי הליבה ואינה דורשת עדכונים.
דוגמה: הוספת כפתור "עדכן מחירים" באמצעות JavaScript:
document.addEventListener('DOMContentLoaded', function () { var toolbar = document.querySelector('.adm-toolbar-panel'); if (!toolbar) return; var btn = document.createElement('input'); btn.type = 'button'; btn.value = 'Обновить цены'; btn.className = 'adm-btn'; btn.addEventListener('click', function () { var form = document.getElementById('list_form'); var action = document.createElement('input'); action.type = 'hidden'; action.name = 'action'; action.value = 'bulk_price_update'; var target = document.createElement('input'); target.type = 'hidden'; target.name = 'target_url'; target.value = '/bitrix/admin/my_bulk_price_update.php'; form.appendChild(action); form.appendChild(target); form.submit(); }); toolbar.appendChild(btn); }); Handler לפעולה המונית ב-PHP
הקובץ document.addEventListener('DOMContentLoaded', function () { var toolbar = document.querySelector('.adm-toolbar-panel'); if (!toolbar) return; var btn = document.createElement('input'); btn.type = 'button'; btn.value = 'Обновить цены'; btn.className = 'adm-btn'; btn.addEventListener('click', function () { var form = document.getElementById('list_form'); var action = document.createElement('input'); action.type = 'hidden'; action.name = 'action'; action.value = 'bulk_price_update'; var target = document.createElement('input'); target.type = 'hidden'; target.name = 'target_url'; target.value = '/bitrix/admin/my_bulk_price_update.php'; form.appendChild(action); form.appendChild(target); form.submit(); }); toolbar.appendChild(btn); }); הוא נקודת הכניסה. הוא מקבל את המזהים של האלמנטים הנבחרים דרך /bitrix/admin/my_bulk_price_update.php, בודק הרשאות, ומבצע את העדכון.
<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_before.php'; $APPLICATION->SetTitle('Массовое обновление цен'); // Проверить права if (!\Bitrix\Main\Engine\CurrentUser::get()->isAdmin()) { die('Access denied'); } $ids = array_map('intval', (array)$_REQUEST['ID']); $ids = array_filter($ids); require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_after.php'; if (!empty($ids) && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm'])) { // Выполнить операцию $markup = (float)$_POST['markup']; foreach (array_chunk($ids, 50) as $chunk) { foreach ($chunk as $id) { $purchase = getPurchasePrice($id); if ($purchase > 0) { updateRetailPrice($id, $purchase * (1 + $markup / 100)); } } } LocalRedirect('/bitrix/admin/iblock_list_admin.php?IBLOCK_ID=' . MY_CATALOG_IBLOCK_ID . '&lang=ru'); } ?> <!-- Форма подтверждения --> <form method="post" action=""> <p>Выбрано товаров: <b><?= count($ids) ?></b></p> <label>Наценка (%): <input type="number" name="markup" value="40" min="0" max="500"> </label> <?php foreach ($ids as $id): ?> <input type="hidden" name="ID[]" value="<?= $id ?>"> <?php endforeach; ?> <input type="hidden" name="confirm" value="Y"> <?= bitrix_sessid_post() ?> <input type="submit" value="Обновить" class="adm-btn-green"> <a href="javascript:history.back()" class="adm-btn">Отмена</a> </form> <?php require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php'; ?> מדוע חשוב לבדוק זכויות גישה?
פעולות המוניות יכולות לשנות אלפי רשומות. ללא בקרת גישה, לחיצה אחת רשלנית יכולה למחוק חצי מהקטלוג. בכל handler, אנו תמיד:
- בודקים את טוקן ה-CSRF דרך
$_REQUEST['ID'][]. - בודקים הרשאות מנהל (
<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_before.php'; $APPLICATION->SetTitle('Массовое обновление цен'); // Проверить права if (!\Bitrix\Main\Engine\CurrentUser::get()->isAdmin()) { die('Access denied'); } $ids = array_map('intval', (array)$_REQUEST['ID']); $ids = array_filter($ids); require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_after.php'; if (!empty($ids) && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm'])) { // Выполнить операцию $markup = (float)$_POST['markup']; foreach (array_chunk($ids, 50) as $chunk) { foreach ($chunk as $id) { $purchase = getPurchasePrice($id); if ($purchase > 0) { updateRetailPrice($id, $purchase * (1 + $markup / 100)); } } } LocalRedirect('/bitrix/admin/iblock_list_admin.php?IBLOCK_ID=' . MY_CATALOG_IBLOCK_ID . '&lang=ru'); } ?> <!-- Форма подтверждения --> <form method="post" action=""> <p>Выбрано товаров: <b><?= count($ids) ?></b></p> <label>Наценка (%): <input type="number" name="markup" value="40" min="0" max="500"> </label> <?php foreach ($ids as $id): ?> <input type="hidden" name="ID[]" value="<?= $id ?>"> <?php endforeach; ?> <input type="hidden" name="confirm" value="Y"> <?= bitrix_sessid_post() ?> <input type="submit" value="Обновить" class="adm-btn-green"> <a href="javascript:history.back()" class="adm-btn">Отмена</a> </form> <?php require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php'; ?>) או דרך מערכת התפקידים של Bitrix. - מאמתים את המזהים שהועברו: הם חייבים להשתייך לבלוק המידע הצפוי — הגנה מפני החלפת אלמנטים זרים.
לפי התיעוד הרשמי של 1C-Bitrix, CAdminContextMenu מאפשר הוספת פריטי תפריט שרירותיים ללא שינוי הליבה.
השוואת שיטות הוספת כפתורים
| שיטה | מורכבות | גמישות | דורשת שינוי ליבה |
|---|---|---|---|
| הזרקת JavaScript | נמוכה | גבוהה (כל כפתור) | לא |
אירוע check_bitrix_sessid() |
בינונית | בינונית (דרך CAdminContextMenu) | לא |
| עריכת קבצי ניהול | גבוהה | גבוהה | כן (אסור בעדכונים) |
אנו ממליצים על הזרקת JavaScript — היא מהירה, לא נוגעת בליבה, ומתאימה בקלות לתרחישים שונים.
פעולות אופייניות והמורכבות שלהן
| סוג פעולה | זמן פיתוח | שורות קוד | דוגמה |
|---|---|---|---|
| עדכון מאפיין אחד | 3 ימים | 50-100 | הגדרת מידה לקבוצת מוצרים |
| תוספת/הנחה לפי מחיר רכישה | 5 ימים | 100-200 | הגדלת מחיר ב-20% |
| לוגיקה מורכבת עם שדות מרובים | 10 ימים | 200-500 | ייבוא מ-Excel עם מיפוי שדות |
סרגל התקדמות לפעולות ארוכות
כאשר מעבדים 1000+ פריטים ללא התקדמות, המשתמש עלול לחשוב שהאתר קפא. אנו מיישמים תבנית AJAX: הפעולה מחולקת לשלבים של 50-100 רשומות כל אחד, כל שלב הוא בקשת AJAX. הסקריפט מחזיר isAdmin(), JavaScript מעדכן את סרגל ההתקדמות ומפעיל את השלב הבא. התור נשמר ב-OnAdminListDisplay או {processed: N, total: M} עם מפתח זמני. תבנית AJAX עם סרגל התקדמות ידידותית פי 10 למשתמש מאשר המתנה ללא משוב.
דוגמה ב-JavaScript:
function processBatch(ids, stepSize, total) { var processed = 0; function next() { if (processed >= total) { alert('Готово'); return; } var batch = ids.slice(processed, processed + stepSize); BX.ajax.post('/bitrix/admin/ajax_bulk.php', { IDs: batch, sessid: BX.bitrix_sessid() }, function(res) { var data = JSON.parse(res); processed += data.batchSize; // Обновить прогресс-бар document.getElementById('progress').style.width = (processed / total * 100) + '%'; next(); }); } next(); } מה כלול בעבודה
- ניתוח — חקר הקטלוג, זיהוי צווארי בקבוק, תיעוד דרישות.
- עיצוב — הגדרת רשימת הפעולות, זכויות גישה, סכימת נתונים.
- יישום — כתיבת קוד באמצעות ORM, הזרקות JS, handlers בשרת.
- בדיקות — בדיקה על עותק של הקטלוג עם 10,000+ פריטים, סימולציית עומס.
- פריסה — העלאה לסביבת הייצור, הגדרת ניטור.
- אחריות — 6 חודשים תמיכה חינמית לבאגים מתועדים.
צרו קשר להערכת פרויקט — נשלח חישוב ראשוני תוך יום עסקים אחד.
טעויות אופייניות בפיתוח פעולות המוניות
- התעלמות ממגבלות זיכרון. בעת עיבוד 50,000 מוצרים ללא חלוקה למנות, הסקריפט יקרוס עם שגיאת 500. השתמשו תמיד בעמודות.
- דילוג על אימות מזהים. אם מערך
$_SESSIONמכיל אלמנטים מבלוק מידע אחר, הפעולה עלולה לשחית נתונים. בדקו דרךb_optionעם פילטר. - חוסר הגנת CSRF. תוקף יכול ליצור קישור עם פרמטרים ולגרום לפעולה לא רצויה. בדקו תמיד sessid.
מידע נוסף על הגנת CSRF
Bitrix משתמשת ב-sessid, שנבדק על ידי הפונקציה check_bitrix_sessid(). כללו תמיד קריאה זו ב-handlers שלכם. עבור בקשת AJAX, העבירו sessid בפרמטרים.בקשו ייעוץ — נבחר את הפתרון האופטימלי עבור הקטלוג שלכם.







