כשכתובת מגיעה לעמוד הלא נכון, ל-404 או לבקר שלא ציפיתם לו, אין צורך לנחש איזה כלל תפס אותה. ה-ROUTER רושם כל החלטה שהוא מקבל, ואפשר להציג את הרשימה הזו בתחתית העמוד עם פרמטר אחד. בעמוד הזה: איך מפעילים, מי רשאי לראות, איך קוראים את הטבלה, ומה עושים כשהפאנל לא מופיע.
הפעלה#
מוסיפים __router_trace לכתובת (הערך לא משנה, העיקר שהפרמטר קיים):
https://example.com/news/5?__router_trace=1
https://example.com/some-friendly-url?__router_trace=1
הפאנל מופיע רק לאחד משלושה:
| מי | התנאי בקוד |
|---|---|
| אדמין מחובר | ADMIN::is_admin() |
| בקשה מהמכונה עצמה | REMOTE_ADDR הוא 127.0.0.1, ::1 או localhost |
| בקשה מכתובת השרת | REMOTE_ADDR שווה ל-SERVER_ADDR |
לכל מבקר אחר הפרמטר פשוט לא עושה כלום, והעמוד נראה כרגיל. כך אפשר גם לבדוק מהשרת בלי להתחבר:
curl -s -H "Host: example.com" "http://127.0.0.1/news/5?__router_trace=1" | grep -o "ROUTER TRACE.*" | head
ההרשאה לפי 127.0.0.1 נשענת על REMOTE_ADDR. אם ה-PHP יושב מאחורי reverse proxy מקומי (nginx אל Apache או php-fpm באותה מכונה) שלא משחזר את כתובת הלקוח האמיתית, כל מבקר נראה ל-PHP כ-127.0.0.1, והפאנל, שחושף את הכללים הפנימיים של הניתוב, ייראה לכולם. בדקו פעם אחת, בלי להתחבר, ש-?__router_trace=1 מדפדפן רגיל לא מציג כלום.
איך הפאנל נראה#
פס קבוע בתחתית החלון (position: fixed, גובה מרבי 45% מהמסך, id="router-trace", dir="ltr") עם כפתור [close] שמסיר אותו. בראשו שורת מצב:
| שדה | משמעות |
|---|---|
request | ה-REQUEST_URI המקורי |
system_type | client או admin (CONFIG::$system_type) |
is_404 | האם PAGE::$is_404 הופעל |
מתחתיה טבלה עם העמודות הבאות, שורה לכל שלב שנרשם, לפי הסדר:
| עמודה | מה בה |
|---|---|
# | המספר הסידורי של השלב |
stage | שם השלב (ראו הטבלה למטה) |
url | הכתובת שנבדקה בשלב הזה |
matched | התבנית או השורה שהתאימה |
note | מה נקבע בעקבות זה (module=..., pageUrl=..., האם הניתוב נעצר) |
ובתחתיתה final $_GET: ערך $_GET כפי שהוא נראה אחרי הניתוב, כולל module, pname ו-id או sys_controller. זה המקום הכי מהיר לבדוק למה בקר קיבל id ריק.
מילון השלבים#
הסדר בטבלה הוא הסדר שבו ה-ROUTER מנסה כללים (ראו ניתוב). שלב שמסתיים ב-return או die עוצר את הניתוב, ולכן מה שאחריו לא יופיע.
שלב (stage) | מתי נרשם |
|---|---|
parse_friendly_url ENTER | תחילת הניתוב, ה-note מכיל את ה-REQUEST_URI |
HOMEPAGE | כתובת ריקה: הבקר הוא CONFIG::$default_module |
NEWPAGE page | p/<slug>: עמוד NEWPAGE, בקר newpage_public |
SCRIPT tag_manager.js | tag_manager.js: בקר minify |
MINIFY js/css | minify/<id>.js או .css |
SCSS (system assets) | assets/<קובץ>.scss.css, קומפילציית SCSS מהליבה |
SCSS (regular file) | <קובץ>.scss.css מהאתר |
STATIC FILE served | קובץ סטטי תחת assets/ שהוגש ישירות |
ADMIN matched | הכתובת מתחילה ב-CONFIG::$admin_url: נקבעים module, pname, id |
ADMIN internal call (ip==server) | קריאה מהשרת עצמו: מדלגים על בדיקת המדינה |
ADMIN Wizzo address (WIZZO_NET) | כתובת של Wizzo: מדלגים על בדיקת המדינה |
ADMIN BLOCKED by country | המדינה לא ברשימה admin_countries: הפניה ל-/ ויציאה |
ADMIN → done | הניתוב של האדמין הסתיים |
CLIENT side | הכתובת היא של צד לקוח, מתחילים לפתור SEO ובקרים |
SEO exact match / SEO exact: none | חיפוש שורת seoUrl מדויקת: נמצאה או לא |
SEO regex match / SEO regex match (decoded) | כלל regex שהתאים (הגרסה השנייה על הכתובת המפוענחת) |
NO SEO → passthrough | אין כלל SEO, הכתובת עצמה משמשת כנתיב |
URL == "404" | הכתובת היא 404: נשלחת כותרת 404 ו-PAGE::$is_404 נדלק |
SYSTEM controller, SYSTEM controller/id, SYSTEM controller/page, SYSTEM controller/page/id | בקר מערכת (system/...), ראו בקרי מערכת |
MODULE module, MODULE module/id, MODULE module/page, MODULE module/page/id | בקר אתר, אותן ארבע צורות |
ROUTER ERROR | אף תבנית לא התאימה (die("router error")) |
MODULE::get_html | נקרא MODULE::get_html, ה-note מכיל את הבקר, המתודה ואם הוא בקר מערכת |
MODULE(system) → ERRORPAGE | בקר מערכת לא נמצא או שהמתודה לא ציבורית |
MODULE → ERRORPAGE | בקר אתר חסר, לא פעיל או בלי המתודה, וה-note אומר איזה מהם |
MODULE activation prompt | הקובץ קיים אבל המודול לא הופעל, ומוצג טופס הפעלה לאדמין |
errorpage() → re-route to "404" | MODULE::errorpage() נכנסת מחדש לניתוב עם 404 (404, 503 ושגיאות) |
דוגמה: למה /blat נותן 404#
# stage url matched note
0 parse_friendly_url ENTER blat REQUEST_URI=/blat?__router_trace=1
1 CLIENT side blat resolving SEO / controller
2 SEO exact: none blat no plain seoUrl row
3 NO SEO → passthrough blat pageUrl = url (raw url used as route)
4 MODULE module blat ^(x)$ module=blat → (controller must exist, else MODULE sends to 404)
5 MODULE::get_html blat/index module='blat' page=index is_system=false
6 MODULE → ERRORPAGE module 'blat' not found/inactive in modules_tbl and no controller file
7 errorpage() → re-route to "404" MODULE returned ERRORPAGE; re-entering ROUTER with url="404"
(הטקסט מקוצר, והשלבים אחרי 7 הם ניתוב מחדש לכתובת 404.) שורה 6 היא התשובה: אין בקר בשם blat. אילו היה קובץ application/controllers/blat.php, השורה הייתה module activation prompt (לאדמין) או MODULE → ERRORPAGE ... active in DB but controller file/class missing, והתיקון שונה לגמרי.
קריאה מתוכנית והוספת שלבים#
ROUTER::$trace הוא מערך סטטי, ואפשר לקרוא אותו מכל קוד, גם בלי להפעיל את הפאנל. שלב נרשם בדיוק באותה צורה גם ממקום אחר, למשל מבקר שמחליט לשלוח לעמוד אחר:
ROUTER::trace('MY RULE', [
'url' => $slug,
'match' => 'legacy-product',
'note' => 'redirecting to product ' . $id,
]);
המפתחות url, match ו-note אופציונליים. ROUTER::is_trace_on() מחזיר true כשהפרמטר קיים והמבקר מורשה, ושימושי אם רוצים להדפיס עוד מידע דיבוג רק במצב הזה:
if (ROUTER::is_trace_on()) {
error_log(json_encode(ROUTER::$trace, JSON_UNESCAPED_UNICODE));
}
כל קריאה ל-ROUTER::trace (בשביל מבקר מורשה עם הפרמטר) רושמת פעם אחת פונקציית register_shutdown_function, שמדפיסה את הפאנל בסוף הבקשה.
מלכודות#
cache_engine::cache_php_check רץ ב-core.php לפני PAGE::load, ובפגיעה במטמון העמוד מוגש ומסתיים שם. מפתח המטמון כולל את מחרוזת השאילתה, ולכן ?__router_trace=1 הוא עמוד נפרד שנוצר בבקשה הראשונה. בעמוד שבקר שלו מפעיל cache_engine::cache_all_page(), הבקשה השנייה לאותה כתובת עם אותו פרמטר תחזור מהמטמון בלי פאנל (הפאנל עצמו לא נשמר, כי הוא מודפס אחרי השמירה). שנו את הערך (?__router_trace=2) או הוסיפו פרמטר אקראי כדי לעקוף.הפאנל מודפס ב-shutdown, ולכן הוא מצורף לסוף כל פלט: גם תשובת JSON או קובץ שנוצר בבקר עם pmode=empg תקבל אחריה <div id="router-trace">. כשאתם בודקים endpoint שמחזיר JSON, אל תוסיפו את הפרמטר לבקשה שה-JS עושה, אלא בדקו אותו בדפדפן או ב-curl נפרד.
הצעדים האחרונים לפני הצגת עמוד מתוך PAGE::load (PAGE::output, ה-theme) לא נרשמים כשלבי ניתוב. ה-trace מכסה את ההחלטה "איזה בקר ומתודה", לא את מה שהבקר עושה אחר כך. לזה משמשים אבחון ולוגים ו-PAGE API.
ראו גם#
- ניתוב: הסדר המלא שהשלבים כאן משקפים.
- כתובות SEO ו-הפניות: מקורות נפוצים לבלבול בין "הכתובת נפתרה" ל"הכתובת הופנתה".
- 404, 503 ושגיאות ו-בקרי מערכת.
- בדיקות: מקומות נוספים לדיבוג בפיתוח.