ניתוב (ROUTER)

איך כתובת URL הופכת לקונטרולר ולמתודה: סדר ההחלטות של ROUTER::parse_friendly_url, המפתחות ש-$_GET מקבל, ופרמטרים בכתובת.

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

כל בקשה שמגיעה ל-index.php עוברת דרך המחלקה ROUTER (system/collections/ROUTER.php). היא לא מריצה קוד של אתר: היא רק קוראת את הכתובת ומכניסה ל-$_GET את המפתחות module, pname, id (או sys_controller לקונטרולר מערכת), וקובעת אם הבקשה היא client או admin. אחריה MODULE::get_html() טוען את הקונטרולר ומריץ את המתודה. בעמוד הזה מתואר הסדר המדויק של ההחלטות, כדי שתדעו לצפות איך כתובת תתפרש לפני שאתם כותבים קונטרולר.

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

איפה הניתוב רץ#

PAGE::load($_SERVER['REQUEST_URI']) מאפס את PAGE, מאתחל PARAMS ו-SEO, וקורא ל-ROUTER::parse_friendly_url($url). בסיום הוא בודק הפניות 301 (ROUTER::redirections(), ראו הפניות 301) וטוען את application/includes. התמונה המלאה של מחזור הבקשה נמצאת ב-מחזור חיי בקשה.

מה ROUTER מחזיר: מפתחות ב-$_GET#

parse_friendly_url לא מחזיר ערך. התוצאה היא מצב גלובלי:

מפתחמתי נקבעמשמעות
CONFIG::$system_typeתמיד"client" או "admin"
$_GET["module"]קונטרולר של אתר, ופאנל ניהולשם הקלאס (וקובץ הקונטרולר)
$_GET["sys_controller"]קונטרולר מערכתשם קובץ ב-system/controllers/
$_GET["pname"]תמידשם המתודה; ריק פירושו index
$_GET["id"]כתובת עם מקטע מספרי או שלישיהמקטע האחרון

ל-pname ריק, MODULE::get_html מחליף ל-index.

סדר ההחלטות#

הבדיקות רצות לפי הסדר הזה, והראשונה שמתאימה מכריעה. רובן מסתיימות ב-return (ללא ה-seoUrl), חלקן מגישות קובץ ויוצאות.

#התנאי (אחרי הסרת / מההתחלה ומהסוף)מה קורה
1פיצול ב-?מה שאחרי ה-? נפרס ב-parse_str ומחליף את $_GET (ראו למטה)
2מצב הסוואהMASK::in($url) מחזיר נתיב אמיתי מנתיב מוסווה
3כתובת ריקהדף הבית: client, module = CONFIG::$default_module, pname = ""
4<32 תווי hex>.txtמפתח IndexNow של חבילת ה-SEO
5poosh-sw.js, tjs.js, pjs.jsקבצי שירות של Wizzo Market, מוגשים מהדומיין של האתר עצמו
6p/<slug>sys_controller=newpage_public, np_slug=<slug> (דף נחיתה של "דף חדש")
7pg.js, pg.cssפרוקסי מטמון לנכסי "דף חדש"
8tag_manager.jsminify/tag_manager
9minify/<id>.js או .cssminify עם id (צינור הנכסים)
10assets/<path>.scss.css ו-<path>.scss.cssminify/scss עם file
11assets/<path>.(js|css|jpg|png|svg|woff2...)אם הקובץ קיים ב-system/assets/, הוא מוגש ב-readfile ויוצא
12קידומת {admin}system_type = "admin": ראו פאנל הניהול
13כל השאר (לקוח)חיפוש ב-seoUrl (כתובות ידידותיות), ואז פירוק הכתובת לפי תבניות

פירוק כתובת של אתר#

אחרי שה-seoUrl החליט מה "הנתיב הפנימי" (או שלא נמצאה התאמה והכתובת עצמה היא הנתיב), הנתיב מפורק ב-regex לפי הסדר. קודם system/..., ואחר כך מודול רגיל:

תבניתדוגמהתוצאה
system/x/<ספרות>system/pdf_viewer/15sys_controller=pdf_viewer, id=15
system/x/y/zsystem/Tools/gallery/3sys_controller, pname=y, id=z
system/x/ysystem/analytics/indexsys_controller, pname=y
system/xsystem/mcpsys_controller=x
x/<ספרות>news/12module=news, id=12 (ללא pname)
x/y/znews/item/12module=news, pname=item, id=12
x/ynews/archivemodule=news, pname=archive
xnewsmodule=news

כל מה שלא מתאים (למשל // באמצע הכתובת) מגיע ל-die("router error").

מקטע שלישי הוא תמיד
id news/item/2024/05 מפורק ל-pname=item ו-id=2024/05: המקטע השלישי לוקח את כל מה שנשאר, כולל לוכסנים. אם אתם צריכים כמה פרמטרים, או שתפרקו את $_GET["id"] בעצמכם, או שתגדירו כתובת ידידותית עם regex.

פרמטרים: id, pname ומחרוזת השאילתה#

קונטרולר קורא את הפרמטרים ישירות מ-$_GET. אין הזרקת ארגומנטים למתודה.

<?php
// application/controllers/news.php
// GET /news/12            -> index()   עם $_GET["id"] = "12"
// GET /news/archive       -> archive()
// GET /news/item/12       -> item()    עם $_GET["id"] = "12"
class news extends wz_controller
{
    function index()
    {
        $id = (int)($_GET["id"] ?? 0);   // תמיד המירו: הערך מגיע כמחרוזת
        if ($id === 0) return $this->view("news/list");

        $row = DB::query("news", ["id" => $id])->get_row();
        if (!$row) return "ERRORPAGE";   // הופך ל-404 (ראו שגיאות)
        return $this->view("news/item", ["row" => $row]);
    }

    function archive() { return $this->view("news/archive"); }

    function item() { return $this->index(); }
}

$_GET מוחלף, לא ממוזג#

כשבכתובת יש ?, הניתוב מבצע $_GET = $arrget: המערך שנבנה מה-REQUEST_URI מחליף את מה ש-PHP בנה. התוצאה בדרך כלל זהה, אבל שני הבדלים חשובים:

  • הפיצול הוא explode("?", $url) בלי הגבלה, ולכן אם יש בכתובת שני סימני ?, רק החלק שבין הראשון לשני נקרא.
  • פרמטרי מעקב ידועים (utm_*, gclid, fbclid ועוד, הרשימה ב-cache_engine::$tracking_params) מוסרים מה-REQUEST_URI לפני הניתוב, בשביל מטמון העמודים. הניתוב מחזיר אותם ל-$_GET מהמקור, כך שהם זמינים לקוד שלכם.

פרמטרים שה-seoUrl מוסיף דרך ? בנתיב הפנימי (למשל pageurl = news/item?lang=en) ממוזגים לתוך $_GET ודורסים מפתח באותו שם.

pmode: תשובה בלי עטיפת HTML#

אם $_GET["pmode"] הוא empg או inner, PAGE::output() לא עוטף את הפלט ב-theme וב-<html>: מוחזר רק מה שהקונטרולר החזיר. כך נכתבים נתיבי JSON וקבצים, למשל /news/feed?pmode=empg. (ב-PAGE::output נשלחות גם כותרות scripts ו-scripts_ver עם רשימת הנכסים.)

ה-API הציבורי של ROUTER#

חתימהמה עושה
ROUTER::parse_friendly_url(string $url)הניתוב עצמו; ממלא $_GET ו-CONFIG::$system_type
ROUTER::redirections()בודק את טבלת redirections ועונה 301; ראו הפניות 301
ROUTER::get_seo_tbl()כל שורות seoUrl לפי ord, במטמון seoUrl_tbl
ROUTER::get_by_url($url)נתיב פנימי => הכתובת הידידותית שלו (או הנתיב עצמו אם אין)
ROUTER::get_by_friendly($url)כתובת ידידותית => הנתיב הפנימי (או הכתובת עצמה אם אין)
ROUTER::remove_by_url($url)מוחק שורות seoUrl שה-pageurl שלהן שווה ל-$url
ROUTER::is_trace_on()האם מצב הדיבוג דלוק לבקשה הזו
ROUTER::trace($stage, $detail = [])רושם שלב בהחלטה (url, match, note)
ROUTER::trace_render()מדפיס את הפאנל; נרשם אוטומטית ב-shutdown
ROUTER::$traceמערך השלבים שנרשמו

הכתובת הידידותית לרשומה (כשיש seoUrl) נוצרת כך:

$url = ROUTER::get_by_url("news/item?id=" . (int)$row["id"]);   // "my-news-title" או הנתיב עצמו
echo "<a href=\"/" . htmlspecialchars($url) . "\">" . htmlspecialchars($row["title"]) . "</a>";
שימו לב
die("router error") ו-die("URL ERROR") עונים 200 כתובת שלא מתאימה לאף תבנית, ובקשה לדומיין שלא מופיע ב-platforms.domain או ב-allowed_domains (כש-CONFIG::$ignore_domain_check אינו true), מסתיימות ב-die עם סטטוס 200 וללא רישום ל-error_log. לכלי ניטור שמסתמכים על קוד סטטוס זה נראה כמו עמוד תקין.

שם קונטרולר הוא שם קובץ ושם קלאס

החלק הראשון בכתובת הופך ישירות לשם קלאס וקובץ ב-application/controllers/<name>.php. בשרת Linux השם רגיש לאותיות גדולות וקטנות, והתו היחיד שאסור בו הוא /. קונטרולר ששמו p יתנגש עם /p/<slug> (המסלול של "דף חדש" נבדק קודם), ושם system לא יהיה זמין כמודול.

ראו גם#

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