פיתוח ישויות ORM D7 מותאמות אישית עבור 1C-Bitrix
אנחנו עובדים עם 1C-Bitrix כבר למעלה מ-10 שנים ורואים פרויקטים רבים סובלים מכאוס במסד הנתונים: שאילתות SQL גולמיות בקומפוננטות, לוגיקה כפולה וסוגים חסרים. ORM D7 הוא הכלי שהופך כאוס לסדר. ישות DataManager מתארת טבלה, שדותיה ויחסיה, כך שבמקום $DB->Query אתה כותב MyTable::getList([...]). עם ניסיון של 10+ שנים, יישמנו 50+ פרויקטים על ORM D7 — ממודולים מותאמים אישית קטנים ועד להחלפה מלאה של סכמות legacy בקטלוגים עם מיליוני רשומות.
למה ORM D7 עדיף על שאילתות SQL גולמיות?
שאילתות SQL ישירות דרך $DB->Query הן נחלת העבר. הן קשות לתחזוקה, אינן מספקות אובייקטים טיפוסיים, ואינן משתלבות עם מטמון Bitrix. ORM D7 פותר את כל הבעיות הללו: הקוד הופך לקריא, בטוח (escape אוטומטי), ומהירות הפיתוח גדלה פי 2–3 בהשוואה ל-SQL גולמי. יתרה מזאת, ישויות ORM עובדות עם מטמון מתויג (tagged cache), שנפסל רק כאשר הנתונים משתנים, לא לפי טיימר. זה חשוב במיוחד בפרויקטים בעלי עומס גבוה. מניסיוננו, שיפורי מטמון בלבד מפחיתים שאילתות DB עד פי 4, וזמני טעינת עמודים יורדים פי 6.
מבנה בסיסי של DataManager
ישות מינימלית נראית כך:
namespace MyProject\Storage; use Bitrix\Main\ORM\Data\DataManager; use Bitrix\Main\ORM\Fields\IntegerField; use Bitrix\Main\ORM\Fields\StringField; use Bitrix\Main\ORM\Fields\DatetimeField; class OrderLogTable extends DataManager { public static function getTableName(): string { return 'my_order_log'; } public static function getMap(): array { return [ new IntegerField('ID', [ 'primary' => true, 'autocomplete' => true, ]), new IntegerField('ORDER_ID', [ 'required' => true, ]), new StringField('ACTION', [ 'required' => true, 'size' => 100, ]), new DatetimeField('CREATED_AT', [ 'default_value' => new \Bitrix\Main\Type\DateTime(), ]), ]; } } רשום את המחלקה במפת ה-autoload של המודול או דרך PSR-4 ב-namespace MyProject\Storage; use Bitrix\Main\ORM\Data\DataManager; use Bitrix\Main\ORM\Fields\IntegerField; use Bitrix\Main\ORM\Fields\StringField; use Bitrix\Main\ORM\Fields\DatetimeField; class OrderLogTable extends DataManager { public static function getTableName(): string { return 'my_order_log'; } public static function getMap(): array { return [ new IntegerField('ID', [ 'primary' => true, 'autocomplete' => true, ]), new IntegerField('ORDER_ID', [ 'required' => true, ]), new StringField('ACTION', [ 'required' => true, 'size' => 100, ]), new DatetimeField('CREATED_AT', [ 'default_value' => new \Bitrix\Main\Type\DateTime(), ]), ]; } } בתוך composer.json.
סוגי שדות ORM
| מחלקת שדה | סוג DB | תכונות מיוחדות |
|---|---|---|
/local/ |
INT | מפתח ראשי, השלמה אוטומטית, unsigned |
IntegerField |
VARCHAR | גודל — אורך עמודה |
StringField |
TEXT | למחרוזות ארוכות |
TextField |
FLOAT / DECIMAL | |
FloatField |
TINYINT(1) / CHAR(1) | ערכים — זוג (N/Y) |
BooleanField |
DATE | מחזיר DateField |
\Bitrix\Main\Type\Date |
DATETIME | מחזיר DatetimeField |
\Bitrix\Main\Type\DateTime |
VARCHAR | ערכים — ערכים מותרים |
EnumField |
TEXT / JSON | serialization/deserialization אוטומטי |
אימות שדות מוגדר דרך הפרמטר JsonField.
איך לתאר יחסים נכון ב-DataManager?
אחד-לרבים (Reference) מתואר דרך validation עם מחלקת הישות היעד ותנאי החיבור. לאחר הצהרת היחס, אתה מקבל נתוני טבלה מחוברת בשאילתות.
$result = OrderLogTable::getList([ 'select' => ['ID', 'ACTION', 'ORDER_.USER_ID', 'ORDER_.DATE_INSERT'], 'filter' => ['ORDER_ID' => 42], ]); יצירת הטבלה: מיגרציות
הטבלה נוצרת על ידי מתודת Reference של מחלקת הישות. לשינויי סכמה, השתמש בשאילתות DDL דרך $result = OrderLogTable::getList([ 'select' => ['ID', 'ACTION', 'ORDER_.USER_ID', 'ORDER_.DATE_INSERT'], 'filter' => ['ORDER_ID' => 42], ]); . ל-Bitrix אין מנגנון מיגרציה מובנה — עבור פרויקטים בייצור, אנו משתמשים בסקריפט מיגרציה מותאם אישית.
שאילתות ORM: פעולות בסיסיות
בחירה עם תנאים:
$result = OrderLogTable::getList([ 'select' => ['ID', 'ORDER_ID', 'ACTION', 'CREATED_AT'], 'filter' => [ '>CREATED_AT' => new \Bitrix\Main\Type\DateTime('-7 days'), 'ACTION' => 'STATUS_CHANGED', ], 'order' => ['CREATED_AT' => 'DESC'], 'limit' => 50, ]); while ($row = $result->fetch()) { } הוספה, עדכון, מחיקה מבוצעות דרך createDbTable(), Application::getConnection(), $result = OrderLogTable::getList([ 'select' => ['ID', 'ORDER_ID', 'ACTION', 'CREATED_AT'], 'filter' => [ '>CREATED_AT' => new \Bitrix\Main\Type\DateTime('-7 days'), 'ACTION' => 'STATUS_CHANGED', ], 'order' => ['CREATED_AT' => 'DESC'], 'limit' => 50, ]); while ($row = $result->fetch()) { } . ORM בודק אוטומטית סוגים ומבצע escape לערכים.
מטמון שאילתות
ORM משתלב עם מטמון Bitrix:
$result = OrderLogTable::getList([ 'select' => ['ID', 'ACTION'], 'filter' => ['ORDER_ID' => 42], 'cache' => ['ttl' => 3600, 'cache_joins' => true], ]); המטמון נפסל אוטומטית כאשר הנתונים משתנים דרך מתודות ORM (אם מטמון מנוהל מופעל).
לוחות זמנים ועלויות אופייניים
| משימה | זמן | עלות אופיינית |
|---|---|---|
| 1–3 ישויות פשוטות (ללא יחסים, פעולות CRUD) | 2–4 ימים | $500–$1000 |
| סכמה מורכבת: 5–10 ישויות עם יחסים, אימות, אירועים | 1–2 שבועות | $1500–$3000 |
| החלפה מלאה של טבלאות legacy עם סכמת ORM מותאמת אישית והעברת נתונים | 2–4 שבועות | $3000–$5000 |
לקוחות בדרך כלל חוסכים 30–50% על תחזוקה שנתית לאחר מעבר ל-ORM. ישויות DataManager הן השקעה בקריאות ותחזוקת הקוד. שנה לאחר מכן, מפתח שלא כתב את הקוד הזה יבין את סכמת ה-DB בשעה, לא ביום. SQL גולמי אינו מציע ערובה כזו.
מה כלול בעבודה
- תיעוד סכמת מסד נתונים — תיאור טבלאות, שדות, יחסים ואינדקסים.
- קוד מקור של ישויות — מחלקות DataManager עם אימות ואירועים.
- סקריפטי מיגרציה — ליצירה ושינוי טבלאות, העברת נתונים.
- הוראות פריסה — סדר התקנה ועדכון המודול.
- שבועיים של תמיכה לאחר המסירה — תיקוני באגים, ייעוץ.
דוגמה למיגרציה אופיינית
$conn = \Bitrix\Main\Application::getConnection(); $conn->query("ALTER TABLE my_order_log ADD COLUMN CONTEXT TEXT DEFAULT NULL"); $conn->query("CREATE INDEX idx_order_log_created ON my_order_log (CREATED_AT)"); טעויות נפוצות בשימוש ב-ORM D7
- אינדקסים חסרים — שאילתות מאטות על נפחים מעל 100,000 שורות.
- סוגי שדות שגויים — לדוגמה, StringField במקום TextField, קיצוץ נתונים.
- התעלמות ממטמון — כל שאילתה פוגעת ב-DB למרות שנתונים rarely משתנים.
- הימנעות מיחסים — טעינה ידנית של רשומות קשורות מובילה לשאילתות N+1.
אנו נמנעים מהמלכודות הללו באמצעות בדיקת קוד ובדיקות עומס.
איך אנו מיישמים ישויות ORM: מקרה אמיתי מהפרקטיקה שלנו
פרויקט מהפרקטיקה שלנו: חנות מקוונת עם קטלוג של 300,000 מוצרים. בתחילה, כל הבחירות השתמשו ב-add() עם פרמטרים רבים. הביצועים ירדו; עמודים נטענו ב-5 שניות. פיתחנו שכבת ORM עבור SKU, הנחות ומלאי עבור לקוח זה. תוצאה: זמן יצירת רשימת עמודים ירד ל-0.8 שניות, ומסננים מורכבים לקחו 0.3 שניות. הוספנו גם מטמון מתויג, שהפחית שאילתות DB פי 4. בממוצע, חיסכון בתקציב התחזוקה לפרויקטים כאלה הוא 30–50%.
תהליך העבודה
- אנליזה — אנו חוקרים את מבנה ה-DB הנוכחי, דרישות עסקיות ועומס.
- עיצוב — אנו מציירים את סכמת ישויות ה-ORM, מגדירים יחסים ואינדקסים.
- יישום — אנו כותבים קוד ישויות, מתודות CRUD, אירועים ומטמון.
- בדיקות — בדיקות יחידה, בדיקות עומס עם נפחים אמיתיים.
- פריסה — אנו מיישמים מיגרציות, מעדכנים גישה, מספקים תיעוד.
צור קשר כדי לדון בפרויקט שלך. אנו נעריך מורכבות ונציע לוחות זמנים ללא התחייבות. הזמינו ייעוץ היום.
קרא עוד על ORM ב-ויקיפדיה ו-תיעוד רשמי של 1C-Bitrix (dev.1c-bitrix.ru).







