דלגו לתוכן

או התחילו מנקודה בטוחה: אינדקס הכלים המלא · מפת הטבלאות המרכזיות

מערכת חדשה — 14 יום חינם

מיפוי שדות מטופס לסכימה

עודכן 30.08.2026

אי אפשר לכתוב קוד קליטת טפסים מהזיכרון. סכימת Accounts שונה בין לקוח ללקוח — שדות מותאמים, שדות שהוסרו, שדות שנוספו לפרויקט מסוים — וטבלאות ה‑lookup מחזיקות מזהים שנוצרו במערכת הספציפית הזו.

והמחיר של ניחוש הוא לא שגיאה. הוא הצלחה מדומה:

התהליך — חמישה צעדים, בסדר הזה

Section titled “התהליך — חמישה צעדים, בסדר הזה”
# הצעד למה
1 שליפת סכימת Accounts לדעת אילו שדות קיימים, ובאיזה טיפוס
2 שליפת סכימת טבלת היעד (רק ב‑web2table) אותו דבר עבור השורה העסקית
3 שליפת הערכים מכל טבלת lookup שהטופס ממלא לבנות מפת ערך תצוגה → objectId
4 אימות כל שדה שהלקוח ביקש מול הסכימה לסמן חוסרים לפני כתיבת הקוד, לא אחריה
5 הטמעת המפות בקוד ובנייה רק עכשיו

צעדים 1–3 בלתי תלויים זה בזה — אפשר להריץ אותם במקביל.

Bash
curl -sS "https://api.mbapps.co.il/parse/schemas/Accounts" \
-H "X-Parse-Application-Id: $APP_ID" \
-H "X-Parse-Master-Key: $MASTER_KEY" > accounts-schema.json
JavaScript
import { writeFile } from 'node:fs/promises';
const res = await fetch("https://api.mbapps.co.il/parse/schemas/Accounts", {
headers: {
'X-Parse-Application-Id': APP_ID,
'X-Parse-Master-Key': MASTER_KEY,
},
});
await writeFile('accounts-schema.json', await res.text());
Python
import requests
res = requests.get(
"https://api.mbapps.co.il/parse/schemas/Accounts",
headers={
"X-Parse-Application-Id": APP_ID,
"X-Parse-Master-Key": MASTER_KEY,
},
)
with open("accounts-schema.json", "w", encoding="utf-8") as f:
f.write(res.text)
PHP
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.mbapps.co.il/parse/schemas/Accounts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-Parse-Application-Id: {$APP_ID}",
"X-Parse-Master-Key: {$MASTER_KEY}",
],
]);
$response = curl_exec($ch);
curl_close($ch);
file_put_contents("accounts-schema.json", $response);
Python
# accounts_fields.py — שם שדה, טיפוס, ולאיזו טבלה מצביע כל Pointer
import json
fields = json.load(open('accounts-schema.json', encoding='utf-8'))['fields']
for name, spec in sorted(fields.items()):
print(f"{name:34}{spec['type']:12}{spec.get('targetClass', '')}")

פלט טיפוסי (קטע):

City Pointer CityList
CompanyId String
Email String
F_name String
IsAccount Boolean
LeadSourceId Pointer LeadSource
LeadStatusId Pointer LeadStatuses
Name String
PhoneNumber String
array_interests_Pointer_Interests Array

העמודה השלישית — targetClass — היא מה שאתם צריכים בצעד 3: היא אומרת מאיזו טבלה לשלוף את ערכי ה‑lookup.

שימו לב ל‑City: בהתקנות רבות הוא Pointer לטבלת CityList, כלומר צריך לשלוח objectId ולא שם עיר. בהתקנות אחרות אותו שדה יכול להיות String חופשי. זו בדיוק הסיבה לשלוף סכימה לכל טננט במקום להניח טיפוס.

לסוכן AI או למיישם שעובד מול המערכת דרך שרת ה‑MCP:

JSON
// Get-Schema
{ "className": "Accounts" }
הפרמטר טיפוס חובה מה הוא עושה
className string לא שם המחלקה. בלעדיו — מוחזרת הסכימה של כל הטבלאות במערכת; זו תשובה כבדה (עשרות KB), ומספר הטבלאות תלוי‑התקנה. ה‑MCP משמיט את טבלאות המערכת החסומות (Config, _Session, _Role, SMTP ודומיהן) ולכן מחזיר תמיד כמה טבלאות פחות מ‑/parse/schemas
tablesNameOnly boolean לא true מחזיר רק את שמות הטבלאות — שימושי כדי לאתר את השם המדויק של טבלת היעד

צעד 3 · בניית מפת ה‑Pointer

Section titled “צעד 3 · בניית מפת ה‑Pointer”

<select> בטופס שולח טקסט (“פייסבוק”). ה‑API רוצה objectId (“vOZLqOWnQf”). מישהו צריך לתרגם — ומכיוון שאין לטופס דרך מאובטחת לשאול את המערכת בזמן ריצה, התרגום מוטמע בקוד כמפה סטטית.

JSON
// Get-Data — שליפת ערכי טבלת ה-lookup
{ "table": "LeadSource", "keys": ["Name"], "limit": 200 }
הפרמטר טיפוס חובה הערה
table string שם הטבלה — כלומר ה‑targetClass מהסכימה
keys string[] לא הקרנת שדות. ["Name"] מספיק לבניית מפה
limit number לא ברירת המחדל היא 5 — כמעט תמיד תרצו לציין ערך. המקסימום: 2000
order string לא מיון; - בתחילת השם = יורד
skip number לא עימוד
where object לא תנאי סינון — כל מפתח הוא שם שדה, מפתחות מרובים מתחברים ב‑AND
objectId string לא 10 תווים בדיוק — לשליפת רשומה בודדת. אורך אחר נדחה בוולידציה (Too small / Too big)

מהתוצאה בונים מפה סטטית בקוד:

JavaScript
// נשלף פעם אחת מטבלת LeadSource — עדכנו כשמוסיפים מקור חדש במערכת
const SOURCE_MAP = {
'פייסבוק': 'vOZLqOWnQf',
'גוגל': 'fHG8Rgy8Hr',
'אתר אינטרנט': 'yOTdl4L99Q',
'המלצה': 'Qk2pLm8Zx4',
};

והטופס משתמש בערך התצוגה, בעוד הקוד שולח את המזהה:

HTML
<select name="source">
<option value="">איך הגעתם אלינו?</option>
<option>פייסבוק</option>
<option>גוגל</option>
<option>אתר אינטרנט</option>
<option>המלצה</option>
</select>
JavaScript
const data = { LeadSourceId: SOURCE_MAP[f.source] }; // objectId חשוף, או undefined

טבלת הטיפוסים של שכבת הטפסים

Section titled “טבלת הטיפוסים של שכבת הטפסים”

הטיפוסים כאן אינם הפורמט ב‑JSON של Parse REST. זו הנקודה שבה נשברות הכי הרבה אינטגרציות, כי snippet של Parse REST נראה נכון ומחזיר 200.

הטבלה הזו מפרידה בין שדות account_* לשדות table_* — כי בשדה Pointer שתי הקבוצות מתנהגות אחרת:

טיפוס בסכימה הצורה המומלצת מה קורה בפועל בצורות אחרות
String מחרוזת מחרוזת ריקה אינה נשמרת — השדה כלל לא נכתב לרשומה. אובייקט ({"a":1}) מפיל את הבקשה ב‑400 code 111
Number מספר או מחרוזת מספרית — השרת ממיר 1500 ו‑"1500"1500. "1,500" ו‑"abc" → נשמרים כ‑null
Boolean true / false בוליאני "true" / "false" כמחרוזת (אותיות קטנות בלבד) מומרים; כל מחרוזת אחרת — "True", "yes", "1" — נשמרת כ‑false. מספר (1 / 0) מפיל את הבקשה ב‑400 code 111 (expected Boolean but got Number). חריג: account_IsAccount מקבל רק בוליאני — מחרוזת "true" מפילה את הבקשה
Date מחרוזת ISO שטוחה ומרופדת: "2026-09-01" ISO מלא עובד, וגם {"__type":"Date","iso":"..."} עובד. "2026-9-1" (לא מרופד) מפיל את הבקשה ב‑400 code 111 (expected Date but got String)
Pointeraccount_* מזהה חשוף באורך 10 תווים: "vOZLqOWnQf" {"__type":"Pointer",…} עובד גם הוא. אורך אחר מפיל את כל הבקשה ב‑400
Pointertable_* מזהה חשוף באורך 10 תווים, ורק הוא אורך אחר וגם {"__type":"Pointer",…} נזרקים בשקט200 והשדה חסר. SaleStatusId ב‑Sales נזרק תמיד
Array (בחירה מרובה) מערך של מזהים חשופים: ["uNbbHuMGlK","j17RjXmHdN"] מערך אובייקטי Pointer נשמר כפי שנשלח — לא נזרק, אלא פוגם בנתונים בשקט
File / PrivateFile אסור לשלוח מחזיר 400 — אבל איש הקשר כבר נוצר, ועם אובייקט File נוצרות גם 5 שורות יעד כפולות

מזהה Pointer תקין באורכו אך לא קיים בטבלת ה‑lookup נשמר בשתי הקבוצות — כ‑Pointer שמצביע לשום מקום. גם את זה צריך לתפוס במפה סטטית מעודכנת.

שדה בתבנית array_<purpose>_Pointer_<TargetTable> הוא בחירה מרובה, ומאוחסן כמערך של מזהים חשופים:

JSON
// getlead
{ "PhoneNumber": "0501234567",
"array_interests_Pointer_Interests": ["uNbbHuMGlK", "j17RjXmHdN"] }

ב‑web2table מוסיפים את הקידומת של הקבוצה המתאימה:

JSON
{ "account_array_interests_Pointer_Interests": ["uNbbHuMGlK", "j17RjXmHdN"],
"table_array_tags_Pointer_Tags": ["GGZUYqBjqT", "io3Z6YsMcG"] }

בצד הטופס זה בדרך כלל <input type="checkbox"> מרובים או <select multiple>: אוספים את הערכים הנבחרים, מעבירים כל אחד דרך המפה, ושולחים את המערך שהתקבל.

הכלל: שדה שלא מופה — משמיטים, לא מרוקנים

Section titled “הכלל: שדה שלא מופה — משמיטים, לא מרוקנים”

זו לא העדפת סגנון. שליחת undefined, null או מחרוזת ריקה במקום ערך חסר מייצרת שתי בעיות: undefined לא עובר סריאליזציה בצורה עקבית בין שפות; ובכל שדה — טקסט, Pointer או Date — שכבת הטפסים אמנם משמיטה בעצמה "" ו‑null (השדה כלל אינו נכתב והבקשה מחזירה 200), אבל אתם בונים על התנהגות לא מתועדת של השרת במקום לשלוט בגוף שאתם שולחים. והגבול דק: ערך לא ריק אבל שגוי בטיפוסו — "2026-9-1" בשדה Date, 1 בשדה Boolean, "abc" במקום מזהה ב‑account_* — כבר מפיל את הבקשה כולה ב‑400.

הניקוי הוא שורה אחת, וכדאי שהיא תהיה השורה האחרונה לפני השליחה:

JavaScript
Object.keys(data).forEach((k) => { if (data[k] == null || data[k] === '') delete data[k]; });
Python
data = {k: v for k, v in data.items() if v not in (None, "")}
PHP
$data = array_filter($data, static fn ($v) => $v !== null && $v !== '');

דוגמה מלאה — מסכימה לקוד

Section titled “דוגמה מלאה — מסכימה לקוד”

נניח טופס הרשמה לסדנה. הלקוח ביקש: שם פרטי, שם משפחה, טלפון, אימייל, עיר, “איך שמעת עלינו”, הסדנה שנבחרה, ותאריך התחלה מועדף.

אחרי שליפת הסכימות והמפות, מציגים ללקוח את המיפוי — ורק אז כותבים קוד:

שדות הטופס → שדות המערכת (web2table, table = "CourseRegistrations")
שם פרטי → account_F_name String
שם משפחה → account_L_name String
טלפון → phone String ✔ חובה, בלי קידומת
אימייל → email String בלי קידומת
עיר → account_City String
איך שמעת עלינו → account_LeadSourceId Pointer → LeadSource (מפה: 4 ערכים)
הסדנה → table_CourseId Pointer → Courses (מפה: 6 ערכים)
תאריך מועדף → table_StartDate Date ISO שטוח
⚠ "מספר משתתפים" שביקשתם לא קיים בסכימת CourseRegistrations.
הקרוב ביותר: ParticipantsCount (Number). לאשר לפני שממשיכים.
JavaScript
const SOURCE_MAP = { 'פייסבוק': 'vOZLqOWnQf', 'גוגל': 'fHG8Rgy8Hr', 'המלצה': 'Qk2pLm8Zx4' };
const COURSE_MAP = { 'קורס יסודות CRM': 'aB3dEf9HiJ', 'סדנת אוטומציות': 'kLm4NoP7Qr' };
function buildBody(f) {
const data = {
table: 'CourseRegistrations',
phone: f.phone,
email: f.email,
account_F_name: f.firstName,
account_L_name: f.lastName,
account_City: f.city,
account_LeadSourceId: SOURCE_MAP[f.source], // undefined אם לא נמצא → יימחק
table_CourseId: COURSE_MAP[f.course],
table_StartDate: f.startDate, // "2026-09-01"
};
Object.keys(data).forEach((k) => { if (data[k] == null || data[k] === '') delete data[k]; });
return data;
}
  • נשלפה סכימת Accounts
  • נשלפה סכימת טבלת היעד (web2table)
  • כל שדה שהלקוח ביקש אומת מול הסכימה, וכל חוסר סומן ללקוח לפני כתיבת הקוד
  • לכל Pointer נשלפה טבלת ה‑targetClass ונבנתה מפה
  • כל ערכי המפה הם מחרוזות באורך 10 תווים בדיוק — אורך אחר מפיל את הבקשה כולה (account_*) או נעלם בשקט (table_*)
  • מצביעים נשלחים כמזהה חשוף, לא כאובייקט {"__type":"Pointer"} — בשדות table_* האובייקט נזרק
  • תאריכים כ‑ISO שטוח מרופד ("2026-09-01", לא "2026-9-1" — הלא‑מרופד מפיל את הבקשה)
  • בוליאנים נשלחים כ‑true/false אמיתיים, לא כ‑1/0 (מפיל את הבקשה); account_IsAccount — אף לא כמחרוזת
  • ערכים ריקים מוסרים מהגוף, ו‑0/false לא נמחקים בטעות
  • המפות מתועדות בקוד עם הערה מאיזו טבלה הן נשלפו ומתי