SQL להקמה

איך אתר WIZZO CMS חדש מקבל את הטבלאות שלו: סנכרון מבנה מהשרת הראשי בעדכון גרסה, יצירה עצלה בקוד, וכלי יצירה ידניים, ומה מריצים ידנית בהקמה ראשונה ובאיזה סדר.

⏱ 7 דק' קריאה 1324 מילים ערוך דף זה ב-GitHub

בריפו אין קובץ .sql של הסכמה. מבנה המסד מתגבש משלוש דרכים שפועלות יחד: סנכרון מהשרת הראשי בכל עדכון גרסה, טבלאות שהקוד יוצר לעצמו כשצריך אותן, וכלי יצירה ידניים. הדף מסביר כל אחת, ונותן את הסדר המומלץ להקמת אתר חדש ואת ה-SQL המינימלי שחייבים להריץ בעצמכם.

בעמוד הזה system/ הוא תיקיית הליבה הפרוסה (= api/core בריפו) ו-{admin} הוא CONFIG::$admin_url של האתר.

דרך 1: סנכרון מבנה בעדכון גרסה#

wizzo_update.php::update_db() רצה כחלק מ"עדכון גרסה" בפאנל. היא מורידה מהשרת הראשי את מבנה המסד (https://wizzocms40.wizzo.co.il/system/check_version/db_structure) ומשווה אותו למסד המקומי:

מצבמה היא עושה
טבלה חסרהCREATE TABLE בקידוד utf8mb4 ו-collation utf8mb4_general_ci
עמודה חסרהALTER TABLE ... ADD ומחיקת המטמון table_columns_<table>
עמודה קיימת עם סוג צר יותרהרחבה (safe_widen) רק כשהיא בטוחה ואינה מאבדת נתונים
אינדקס חסרנוסף לפי שם, או מדולג אם קיים כבר אינדקס על אותן עמודות
collation של המסדensure_db_collation() מעדכנת את ברירת המחדל של המסד ל-utf8mb4_general_ci

הטבלאות שמוחרגות מהסנכרון: CRM_trg_*, CRM_users, CRM_buttons*, CRM_newsletter_*.

מפתח ראשי ו-AUTO_INCREMENT

המבנה המיוצא כולל לכל עמודה COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT ו-EXTRA, אבל לא COLUMN_KEY. ה-PRIMARY KEY נוצר בשלב סנכרון האינדקסים (ALTER TABLE ADD PRIMARY KEY), וה-AUTO_INCREMENT נוסף אחריו ב-MODIFY אם חסר. טבלה שנוצרה בדרך הזאת עלולה להיות בלי PK עד שהשלב השני מסתיים.

שגיאות בשלב הזה לא עוצרות את העדכון: פקודה שנכשלה מחזירה false, מודפסת הודעה כמו Error creating table ..., והעדכון ממשיך לטבלה הבאה. בדקו את פלט העדכון.

update_db() לא יכולה ליצור את מה שעדיין לא קיים כדי להריץ את האתר עד לפאנל. לכן בהקמה ראשונה צריך להריץ ידנית לפחות את הטבלאות והשורות שבסעיף "הקמה ראשונה".

סנכרון משימות ה-cron#

באותו עדכון, update_cron_system() מסנכרנת משימות מערכת (קטגוריה id=1) מ-.../system/check_version/cron_system. ההתאמה היא לפי url|params, משימות שנעלמו מהשרת הראשי נמחקות מקומית, ו-last_run, next_run ו-runs_count נשמרים.

דרך 2: יצירה עצלה בקוד#

ספריות ופאנלים רבים בודקים בזמן ריצה אם הטבלה שלהם קיימת, ויוצרים אותה אם לא (ensure_* או CREATE TABLE IF NOT EXISTS). דוגמה אמיתית, CRM_adminPanel_sessions:

CREATE TABLE CRM_adminPanel_sessions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    admin_id INT NOT NULL,
    token VARCHAR(64) NOT NULL,
    ip VARCHAR(45) NOT NULL DEFAULT '',
    user_agent VARCHAR(255) NOT NULL DEFAULT '',
    device_label VARCHAR(100) NOT NULL DEFAULT '',
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    last_active_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    expires_at DATETIME NOT NULL,
    is_impersonated TINYINT(1) NOT NULL DEFAULT 0,
    impersonated_by INT DEFAULT NULL,
    UNIQUE KEY idx_token (token),
    KEY idx_admin_id (admin_id),
    KEY idx_expires (expires_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

כך נוצרות בין השאר: adminPanel_sessions, wizzo_update_log, seo_*, ai_agents*, admin_chat ו-file_manager_log. היצירה העצלה דורשת שלמשתמש המסד יש הרשאות CREATE ו-ALTER, אחרת הכשל נרשם ב-error_log בלבד.

דרך 3: כלים ידניים#

כלימה הוא עושה
פאנל create_tableבונה טבלה CRM_<name> עם id INT AUTO_INCREMENT PRIMARY KEY ורושם אותה כפאנל ניהול
פאנל safe_sqlמריץ רק CREATE TABLE, CREATE INDEX, CREATE UNIQUE INDEX ו-ALTER TABLE ... ADD. ראו מנהל מסד הנתונים
פאנל db_managerיצירת טבלאות, עמודות ואינדקסים בכל צורה, ללא הגבלה
install_db_manager.php הוא קוד מת

הקובץ api/core/admin/install_db_manager.php מנסה לרשום את הפאנל עם DB::insert("adminPanel_panels"), מתודה שלא קיימת. רישום פאנל נעשה בהוספת שורה ל-CRM_adminPanel_panels (ראו הדוגמה למטה, ו-בניית פאנל).

הקמה ראשונה: סדר פעולות#

  1. צרו מסד נתונים בקידוד utf8mb4 ומשתמש עם הרשאות CREATE, ALTER, INSERT, UPDATE, DELETE, SELECT, INDEX.
  2. הגדירו את פרטי החיבור (CONFIG). ראו תצורה.
  3. צרו ידנית את הטבלאות הקריטיות והשורות הראשונות (למטה), או העתיקו מסד של אתר תבנית.
  4. היכנסו לאדמין והריצו עדכון גרסה (עדכוני גרסה). הוא משלים את שאר הטבלאות, העמודות והאינדקסים.
  5. נקו מטמון (ראו ניקוי ותחזוקה).

טבלאות מינימליות#

שחזור מהקוד, לא קובץ רשמי

המבנים שלהלן נגזרו מהאופן שבו הקוד קורא את הטבלאות. סוגי העמודות ואורכיהן הם הצעה סבירה, לא העתק של מבנה השרת הראשי. אחרי עדכון גרסה ראשון, update_db() תרחיב ותשלים מה שחסר.

SET NAMES utf8mb4;
SET sql_mode = '';

CREATE TABLE `CRM_platforms` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `domain` VARCHAR(255) NOT NULL,
  `allowed_domains` TEXT NULL,
  `name` VARCHAR(100) NOT NULL DEFAULT '',
  `direction` VARCHAR(3) NOT NULL DEFAULT 'rtl',
  `ord` INT NOT NULL DEFAULT 0,
  `seo_title` VARCHAR(255) NOT NULL DEFAULT '',
  `seo_keywords` TEXT NULL,
  `seo_description` TEXT NULL,
  `deftheme` VARCHAR(50) NOT NULL DEFAULT 'default',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_domain` (`domain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `CRM_params` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `sysName` VARCHAR(100) NOT NULL,
  `value` TEXT NULL,
  `description` TEXT NULL,
  `perm_developer` TINYINT(1) NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_sysname` (`sysName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

ואחריהן שורות ההתחלה:

-- פלטפורמה ראשונה (= שפה 1). domain חייב להיות בדיוק SERVER_NAME
INSERT INTO CRM_platforms (id, domain, allowed_domains, name, direction, ord, seo_title, deftheme)
VALUES (1, 'www.example.com', '|example.com||localhost|', 'עברית', 'rtl', 1, 'האתר שלי', 'default');

-- פרמטרים שהליבה קוראת תמיד
INSERT INTO CRM_params (sysName, value, description, perm_developer) VALUES
 ('attaches_version', '1', 'cache-buster לנכסים', 1),
 ('log_sql', '0', '1 = לוג כל שאילתה', 1),
 ('cron_runner_token', REPLACE(UUID(),'-',''), 'טוקן לריצת cron_runner', 1);

deftheme יכול להכיל רק [A-Za-z0-9_], כי הוא הופך לשם מחלקה TEMPLATE_<deftheme>.

כניסה ראשונה לאדמין#

כדי להיכנס צריך גם קבוצה, מנהל ופאנלים. הדוגמה למטה ממחישה את הצורה (טבלאות האדמין נוצרות ב-update_db, או ידנית לפי כל הטבלאות). את ה-hash של הסיסמה מייצרים ב-bcrypt:

echo password_hash($plainPassword, PASSWORD_BCRYPT);   // מתחיל ב-$2y$
INSERT INTO CRM_adminPanel_admins_groups (id, name, perms) VALUES (1, 'מנהלים ראשיים', '-1');

INSERT INTO CRM_adminPanel_admins (uname, password, name, email, group_id, skip_otp)
VALUES ('admin', '<BCRYPT_HASH>', 'Admin', 'admin@example.com', 1, 1);

INSERT INTO CRM_adminPanel_panels_categories (id, name, ord) VALUES (3, 'כלים למפתחים', 9);
INSERT INTO CRM_adminPanel_panels (category, panel_name, text, icon, ord, perm_developer)
VALUES (3, 'db_manager', 'מנהל מסד נתונים', '<i class="fa fa-database"></i>', 2, 1);

panel_name הוא שם הקובץ שבתיקיית הפאנלים (api/core/admin/<panel_name>.php, או application/admin/ באתר) והוא רגיש לאותיות גדולות וקטנות בלינוקס. skip_otp = 1 מדלג על קוד חד-פעמי במייל או SMS. כבו אותו אחרי הכניסה הראשונה.

סיסמה

אל תשמרו סיסמה גלויה במסד ואל תשאירו מנהל עם סיסמה ידועה מראש. החליפו אותה מיד אחרי הכניסה הראשונה.

אחרי יצירה ידנית: ניקוי מטמונים#

שלושה נתונים נשמרים במטמון ימים רבים, ושינוי ישיר ב-SQL לא יופיע עד שמוחקים אותם:

מפתחTTLמתי למחוק
platforms30 יוםהוספת דומיין או שינוי פלטפורמה
params30 יוםשינוי ב-CRM_params
table_list7 ימיםיצירת טבלה (כולל _content)
cache_engine::remove("platforms");
cache_engine::remove("params");
cache_engine::remove("table_list");

או מהאדמין: ניקוי ותחזוקה.

ראו גם#

מצאתם טעות או חוסר? תקנו את הדף או פתחו Issue בריפו. התיעוד נכתב מתוך הקוד של ליבה 5.0.115.