מבנה התיקיות של אתר

מפת התיקיות של אתר WIZZO CMS פרוס: מה יושב בכל תיקייה, איזה קובץ בליבה קורא אותה, האם היא נכתבת בזמן ריצה, ומה שייך לליבה ומה לאתר.

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

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

נתיבי קבצי ליבה כתובים יחסית ל-api/core בריפו (collections/ROUTER.php). באתר פרוס התיקייה הזו נקראת system/core/, ראו את ההתאמה בסוף הדף. כתובות כמו /system/mcp הן URL של קונטרולר מערכת, לא תיקייה בדיסק (קונטרולרי מערכת).

המבנה במבט אחד#

<שורש האתר>/                 = CONFIG::$base_path
├── index.php                 נקודת הכניסה היחידה
├── .htaccess                 כללי Apache: front controller, cache סטטי, https
├── robots.txt                קובץ סטטי (לא נוצר על ידי הליבה)
├── sqllog.txt                נוצר כש-SQL logging דלוק
├── composer.json, vendor/    אופציונלי: חבילות Composer של האתר
├── system/                   הליבה ונתוני מערכת
│   ├── core/                 = api/core של הריפו
│   ├── js/                   = api/js של הריפו
│   ├── config.php            מגדיר class CONFIG_USER
│   ├── .htaccess             מגן על קבצי הקונפיגורציה (נכתב אוטומטית)
│   ├── system_tags.json
│   ├── accessibility_config.json
│   ├── admin_countries.json
│   └── market_settings.json  רק כשהאתר מחובר ל-Wizzo Market
├── application/              הקוד של האתר
│   ├── controllers/          קונטרולרים של האתר
│   ├── models/               models
│   ├── views/                תבניות .tpl של קונטרולרים
│   ├── includes/             PHP שנטען בכל בקשה של צד הלקוח
│   ├── admin/                פאנלי ניהול של האתר
│   │   └── includes/         PHP שנטען רק באדמין
│   ├── ai_tools/             כלי AI ישנים (ai_cron)
│   └── views_mobile/         לא בשימוש
├── themes/<name>/            ערכות עיצוב של האתר
├── cache/                    מטמון (נכתב בזמן ריצה)
└── media/                    קבצים שהועלו (נכתב בזמן ריצה)
שורש האתר הוא CONFIG::$base_path
CONFIG::preinit() קובע את $base_path כתיקיית סקריפט הכניסה (collections/CONFIG.php:35-37). כל נתיב "ביחס לאתר" בליבה (application/..., themes/..., media/...) נבנה ממנו. אין בליבה chdir, ולכן נתיבים יחסיים כמו cache/Smarty/templates_c/ או system/js/*.js מניחים שתיקיית העבודה של התהליך היא שורש האתר. השרת מבטיח זאת לבקשת HTTP רגילה; הרצה מ-CLI חייבת להתחיל מהשורש.

הטבלה: מי קורא, האם נכתב, למי שייך#

נתיבנקרא על ידינכתב בזמן ריצהשייך ל-
index.phpApache (נקודת כניסה)לאאתר
.htaccessApacheלאאתר
system/core/index.php דרך CONFIG::$core_pathרק בעדכון ליבהליבה
system/js/PAGE::load (glob("system/js/*.js"), PAGE.php:755)רק בעדכון ליבהליבה
system/config.phpindex.phpלאאתר
system/.htaccessApacheכן (market_service)אתר (הליבה מנהלת בלוק בתוכו)
system/*.jsonmarket_service, PAGE, admin_countriesכןאתר
application/controllers/MODULE::get_controller_file_srcלאאתר
application/models/MODULE דרך CONFIG::$models_folderלאאתר
application/views/MODULE::viewלאאתר
application/includes/core.php (init.php) ו-PAGE::loadלאאתר
application/admin/AdminModuleלאאתר
application/admin/includes/PAGE::load באדמין, AGENT_TOOLSלאאתר
application/ai_tools/controllers/ai_cron.phpלאאתר
themes/<name>/PAGE, bgl_themeלאאתר
cache/cache_engine, Smarty, SCSS, minifyכן, חובהאתר (תוצר)
media/STORAGEכן, חובהאתר (נתוני משתמש)
sqllog.txtDB::log_sql_to_file, פאנל sqllogכן, כשהלוג דלוקאתר

עמודת "נכתב בזמן ריצה" אומרת שמשתמש ה-web server (Apache או PHP-FPM) צריך הרשאת כתיבה. ההרשאות של שאר התיקיות יכולות להיות לקריאה בלבד, חוץ מעדכון ליבה שמפורט בהמשך.

index.php ו-.htaccess#

index.php הוא הקובץ היחיד ש-Apache מריץ. הוא טוען את system/config.php, ממיר את core_path לנתיב מוחלט וטוען את core.php (הפרטים ב-קונפיגורציה). אין בו לוגיקה עסקית.

ה-.htaccess בשורש הוא שמחבר את הבקשות אל הליבה. הנקודות המהותיות:

  • ErrorDocument 404 /404, והפניות 301 מ-www ל-non-www ומ-http ל-https.
  • קובצי מטמון סטטיים מוגשים ישירות מ-cache/%{SERVER_NAME}/... כשהם קיימים, והבקשה לא מגיעה ל-PHP. אם הקובץ לא קיים, *.scss.css ו-minify/*.js|css מנותבים ל-index.php.
  • גישה ישירה לקובצי .chc תחת cache/items/ חסומה.
  • כלל ה-front controller: כל בקשה שאינה קובץ קיים נשלחת ל-index.php, חוץ מנתיבים שמוגשים סטטית.
RewriteCond $1 !^(\.well-known)
RewriteCond $1 !^(firebase-messaging-sw\.js)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $1 !^(index\.php|cache|application/views|application/views_mobile|system/js|system/libraries|system/css|media|themes)
RewriteRule ^(.*)$ /index.php?%{QUERY_STRING} [L]

התנאי האחרון מחריג תיקיות שמוגשות כקבצים סטטיים (cache, system/js, media, themes ועוד): בקשה לנתיב שמתחיל באחת מהן ואינו קובץ קיים לא נשלחת ל-index.php. כל נתיב אחר שאינו קובץ קיים, כולל כל URL של דף, מגיע ל-index.php.

הניתוב עצמו מתואר ב-ניתוב (ROUTER) וב-מחזור חיי בקשה.

system/: ליבה ונתוני מערכת#

system/core/ ו-system/js/#

system/core/ הוא הקוד של הליבה (collections/, libraries/, controllers/, admin/, themes/, views/, assets/, addons/, core.php, version.txt). אל תערכו בו בקובץ: הוא מוחלף כולו בכל עדכון ליבה. system/js/ הוא קבצי ה-JS של צד הלקוח (system.js, jquery.min.js, MISC.js, analytics.js) ש-PAGE::load מצרף לכל עמוד. הקובץ system/js/system.js נטען ב-head והשאר בסוף ה-body (ה-JS שנטען בכל עמוד).

כתובות שמתחילות ב-/assets/ מוגשות מ-system/core/assets/ על ידי ROUTER (קריאת קובץ ישירה), אז נכסי הפאנל (CKEditor, FontAwesome ועוד) לא דורשים תיקיית assets בשורש האתר.

עדכון ליבה (admin/wizzo_update.php) פורס את הגרסה החדשה לתיקייה אחות core_new_<תאריך> ליד system/core/, מחליף ושומר את הישנה כ-core_bup_<תאריך>. עדכון ה-JS עושה אותו דבר עם js_bup_<תאריך> בתוך $_SERVER['DOCUMENT_ROOT'] . "/system". לכן תיקיית system/ צריכה להיות ניתנת לכתיבה לתהליך העדכון, ובמהלך העדכון נדרש מקום פנוי בדיסק לכמה עותקים של הליבה. ראו עדכון ליבה.

גיבויי core_bup_ ממלאים דיסק

כל עדכון משאיר תיקיית core_bup_* ו-js_bup_*. cleanup_old_backups מנקה גיבויים ישנים, אבל על שרת עם מעט מקום פנוי הם עלולים למלא את הדיסק. בדקו מקום פנוי לפני עדכון.

system/config.php#

מגדיר class CONFIG_USER. הוא נטען לפני הליבה, ואין לליבה אפשרות לטעון אותו בעצמה. פירוט מלא: קונפיגורציה.

system/.htaccess#

כתוב ומנוהל על ידי libraries/market_service.php (protect_settings_dir, market_service.php:120). הוא חוסם גישת HTTP לקבצים שהליבה קוראת מהדיסק, ולכן ההגנה לא פוגעת בתפקוד. הוא כולל רק כללי FilesMatch (בלי RewriteEngine, כדי לא לשבור את כללי הניתוב מהשורש):

<FilesMatch "^(market_settings\.json.*|system_tags\.json|config\.php|.*_keys?\.json|\..*)$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order allow,deny
        Deny from all
    </IfModule>
</FilesMatch>

כללים שהאתר הוסיף מחוץ לבלוק המנוהל נשמרים בכל עדכון של הבלוק.

שרת שאינו Apache

ההגנה היא קובץ .htaccess, ולכן ב-nginx או ב-LiteSpeed בלי תאימות ל-.htaccess היא לא פועלת. חסמו את system/config.php ואת קבצי ה-.json בתצורת השרת עצמה. ראו הקשחה.

קבצי JSON של system/#

קובץנקרא על ידיתפקיד
system_tags.jsonPAGE.php:632, market_service.php:387תגיות מערכת (tag manager) שמוזרקות לעמודי צד-לקוח
accessibility_config.jsonmarket_service.php:320הגדרות תוסף הנגישות
admin_countries.jsonlibraries/admin_countries.php:7מדינות מותרות להתחברות לפאנל. קודם ל-CONFIG::$admin_countries
market_settings.jsonmarket_service.php, AdminModule, connectorהגדרות החיבור ל-Wizzo Market. קיים רק אחרי חיבור, ומכיל מפתחות: Wizzo Market

הקבצים נכתבים מפאנלי הניהול או מחיבור ל-Market, ולכן system/ צריכה להיות ניתנת לכתיבה גם בזמן ריצה, לא רק בעדכון.

application/: הקוד של האתר#

התיקייה הזו כולה שלכם. אין בה קובץ שהליבה מספקת, והליבה לא מעדכנת בה דבר.

תת-תיקייהמה הליבה עושה איתה
controllers/<name>.phpMODULE::get_controller_file_src טוענת application/controllers/<name>.php ומאתחלת מחלקה בשם <name>. הקונטרולר חייב גם שורה פעילה ב-CRM_modules: קונטרולרים של אתר
models/$this->load->model("x") טוען את CONFIG::$models_folder/x.php (MODULE.php:226). הנתיב נקבע ב-קונפיגורציה
views/$this->view("home/index") מרנדר application/views/home/index.tpl (MODULE.php:206) דרך Smarty: תבניות Smarty
includes/core.php טוען את init.php מיד אחרי CONFIG::init() (בכל בקשה, כולל אדמין ו-CLI). בבקשות צד-לקוח PAGE::load טוענת בנוסף את כל *.php בתיקייה לפי סדר שם קובץ (FILES::include_dir)
admin/<panel>.phpפאנל ניהול של האתר: מחלקה ADMINMODULE_<panel>. AdminModule::get בודקת קודם system/core/admin/<panel>.php, ורק אם אין שם קובץ באותו שם טוענת את application/admin/<panel>.php (פאנל בליבה גובר על פאנל של האתר בשם זהה). רשומה ב-CRM_adminPanel_panels נדרשת: בניית פאנל
admin/includes/נטען רק באדמין (PAGE.php:806). כאן רושמים AGENT_TOOLS::add_tool לכלי MCP של האתר: כתיבת כלי MCP לאתר
ai_tools/<name>.phpנקרא רק על ידי controllers/ai_cron.php (application/ai_tools/<name>.php, מחלקה ai_tool_<name>): סוכני AI
views_mobile/לא בשימוש. קיים ברשימת הנתיבים הסטטיים של ה-.htaccess ובקוד מוער ב-FILES.php:194, וההחלפה לתבנית מובייל בוטלה
שני מקומות ל-includes
application/includes/ חל על צד הלקוח (וגם init.php על אדמין), ו-application/admin/includes/ חל על האדמין בלבד. קוד שחייב להיות זמין בשניהם (חיבור ל-autoload של Composer, הגדרת LOGIN::$table) שייך ל-application/includes/init.php.

themes/: ערכות העיצוב של האתר#

כל ערכה היא תיקייה themes/<name>/. הקובץ index.php שלה מגדיר מחלקה TEMPLATE_<name> extends bgl_theme, ו-PAGE טוענת אותו (PAGE.php:456) כשהפלטפורמה או הקוד בחרו את הערכה (PAGE::set_theme, ברירת מחדל מ-CRM_platforms.deftheme). את index.tpl שבתיקייה מרנדר bgl_theme::get_html (collections/theme.php).

themes/default/
├── index.php        class TEMPLATE_default extends bgl_theme
├── index.tpl        השלד של העמוד (Smarty)
├── css/ , assets/ , fonts/ , images/ , HTML/
├── funcs.js , ui.js

שתי ערכות שייכות לליבה ולא לאתר: admin_login ו-admin_panel. הן נטענות מ-system/core/themes/ (PAGE.php:446-449), ואין לשכפל אותן ל-themes/ של האתר. פירוט: ערכות נושא (Themes) ו-צינור הנכסים.

cache/: המטמון#

התיקייה נכתבת על ידי PHP בכל בקשה, ו-Apache מגיש ממנה קבצים סטטיים ישירות. מבנה נפוץ (שמות הדומיינים הם SERVER_NAME של הבקשה):

cache/
├── *.chc.gz                      מטמון נתונים גלובלי (platforms, params, table_list, minify_groups...)
├── items/                        פריטי cache_engine גלובליים
├── Smarty/templates_c/           תבניות Smarty מקומפלות
├── Smarty/cache/                 מטמון Smarty
├── composer/                     נתוני ניהול Composer
├── perf_advisor/                 נתוני יועץ הביצועים
└── <SERVER_NAME>/                תיקייה נפרדת לכל דומיין
    ├── pages/ , pages_mobile/    page cache מלא
    ├── scss/                     SCSS מקומפל
    ├── minify/                   JS ו-CSS מאוחדים
    └── locks/ , locks_mobile/    נעילות בנייה

שלושה פרטים שחשוב להכיר:

  • המטמון מפוצל לפי דומיין: get_platform_cache_folder() מחזיר CONFIG::$cache_folder . '/' . $_SERVER["SERVER_NAME"] (cache_engine.php:81-103). שם host שמכיל /, \ או .. מוחלף בשם בטוח.
  • מטמוני ה-SCSS, ה-minify וה-Smarty כתובים בקוד כ-cache/... יחסי ל-שורש האתר, ללא קשר ל-CONFIG::$cache_folder (FILES.php:10, FILES.php:435, controllers/minify.php:90).
  • כל מה שבתיקייה ניתן למחיקה בבטחה: המטמון נבנה מחדש לפי דרישה.
cache/ ללא הרשאת כתיבה

אם PHP לא יכול לכתוב ל-cache/, האתר עדיין עונה, אבל איטי: כל בקשה מקמפלת Smarty ו-SCSS מחדש. בדקו קודם כול את הרשאות התיקייה כשהאתר איטי באופן פתאומי. ראו איך המטמון עובד ו-מטמון עמודים מלא.

media/: קבצים שהועלו#

STORAGE שומרת קבצים שהועלו ב-media/Storage (ברירת מחדל, STORAGE.php:215), ותמונות זמניות של עיבוד תמונה ב-media/System/CropTmp (STORAGE.php:7). תיקיות נוספות שהליבה כותבת אליהן: media/seo (תמונות Open Graph של פאנל ה-SEO) ו-media/Modules (תמונות של פאנלים).

media/
├── Storage/          העלאות (ברירת המחדל של STORAGE)
├── System/CropTmp/   קבצי ביניים של עיבוד תמונה
├── seo/              תמונות OG
├── Modules/          תמונות של פאנלי ניהול
└── .htaccess         php_flag engine off

הליבה לא יוצרת את media/.htaccess. באתר הייחוס הוא מכיל php_flag engine off, ומבטל הרצת PHP בתיקייה. מומלץ להוסיף אותו בכל אתר, כי זו תיקייה שמקבלת קבצים מהמשתמשים (כללי העלאת קבצים).

כש-CONFIG::$storage_remote הוא "ftp" או "s3", הקבצים נשמרים גם או רק בשרת מרוחק, אבל תיקיית media/System/CropTmp נשארת בשימוש מקומי. ראו STORAGE: העלאה ואחסון.

תיקיות storage נוספות

פאנלי המדיה של שירותי Market (newpage_media, poolse_media, target_media) כותבים ל-storage/newpage, storage/poolse ו-storage/target בשורש האתר (נתיב CONFIG::$base_path . "/storage/..."). אלה נוצרות רק כשהשירותים בשימוש.

קבצים נוספים בשורש#

  • robots.txt: קובץ סטטי של האתר. הליבה לא מייצרת אותו, והיא רק קוראת אותו בבדיקות SEO. ראו תגיות SEO.
  • sqllog.txt: נוצר על ידי DB::log_sql_to_file כשפרמטר המערכת log_sql שווה "1" (DB.php:71,331). הקובץ גדל בלי הגבלה, ולכן מדליקים אותו לזמן דיבוג בלבד: דיבוג SQL.
  • composer.json, composer.lock, vendor/: חבילות Composer של האתר. הליבה מנהלת אותם דרך ComposerManager (שורש הניהול הוא $base_path), והם נפרדים מהספריות של הליבה ב-system/core/addons/. ראו חבילות Composer.

ריפו מול אתר פרוס#

הריפו של הליבה הוא לא עותק של אתר. רק שתי תיקיות ממנו מגיעות לאתר:

בריפובאתר פרוס
api/core/system/core/
api/js/system/js/

כל השאר (website/, docs/, publish_scripts/, promo_video* וכן הלאה) הוא כלי פיתוח, תיעוד ופרסום, ולא נפרס. שורש האתר (index.php, .htaccess, application/, themes/, system/config.php) נוצר בהתקנה ושייך לאתר. תיאור הריפו: מבנה הריפו, והתקנה: התקנת אתר חדש.

איפה אני עורך מה

שינוי בליבה נעשה בריפו (api/core) ומתפרסם בעדכון גרסה לכל האתרים. שינוי שמשרת אתר אחד בלבד נעשה ב-application/ או ב-themes/ של אותו אתר. עריכת קובץ ישירות תחת system/core/ של אתר חיה עד העדכון הבא ואז נמחקת.

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