כשכתובת עוברת למקום חדש, מוסיפים שורה בטבלה CRM_redirections והליבה עונה 301 Moved Permanently עם כותרת Location. ההפניות הן התאמה מדויקת של נתיב לנתיב: אין תבניות ואין wildcard (לביטויים רגולריים משתמשים ב-seoUrl, שמתרגם כתובת לנתיב פנימי אבל לא מפנה).
system/ בעמוד הזה הוא תיקיית הליבה הפרוסה (api/core בריפו), ו-{admin} הוא CONFIG::$admin_url.
הטבלה והפאנל#
| עמודה | משמעות |
|---|---|
id | מפתח |
url_from | הנתיב הישן, בלי / בהתחלה ובסוף ובלי מחרוזת שאילתה |
url_to | היעד: נתיב יחסי לאתר, או כתובת מלאה |
הפאנל ADMINMODULE_redirections (system/admin/redirections.php, הכתובת {admin}/redirections) מציג רשימה ופותח טופס בחלון קופץ עם שני שדות: "מכתובת" (חובה) ו"לכתובת". לפני השמירה הוא מסיר מכל שדה את CONFIG::$site_url ומקצץ / מההתחלה ומהסוף, כך שאפשר להדביק כתובת מלאה מהדפדפן. שמירה ומחיקה מנקות את המטמון redirections.
הוספה מקוד#
$q = DB::update("redirections");
$q->set_var("url_from", "old-products/shoes");
$q->set_var("url_to", "products/shoes");
$q->insert();
cache_engine::remove("redirections"); // בלי זה הכלל לא ייראה עד שהמטמון יפוג
גם מ-SQL אפשר, ובלבד שמנקים את המטמון אחר כך:
INSERT INTO CRM_redirections (url_from, url_to) VALUES ('old-page', 'new-page');
האלגוריתם#
ROUTER::redirections() נקרא מ-PAGE::load מיד אחרי ROUTER::parse_friendly_url, ורק בצד לקוח (CONFIG::$system_type == "client"). הוא:
- טוען את כל הטבלה כמפה
url_from => url_to, במטמוןredirectionsל-7 ימים. - לוקח את
$_SERVER['REQUEST_URI'], מקצץ/מהקצוות ומפצל ב-?לנתיב ולמחרוזת שאילתה. - מחפש את הנתיב במפה, ואם לא נמצא, מחפש את
urldecodeשלו (כתובות בעברית). - אם נמצא: אם היעד לא מכיל את המחרוזת
http, מוסיף לו/בהתחלה. מחרוזת השאילתה המקורית מצורפת ליעד (עם&אם ביעד כבר יש?, אחרת עם?). - שולח
301ו-Locationומסיים את הבקשה עםexit.
url_from | url_to | בקשה | תשובה |
|---|---|---|---|
old-page | new-page | /old-page | 301 Location: /new-page |
old-page | new-page | /old-page?ref=mail | 301 Location: /new-page?ref=mail |
old-page | new-page?a=1 | /old-page?ref=mail | 301 Location: /new-page?a=1&ref=mail |
old-page | https://example.org/x | /old-page | 301 Location: https://example.org/x |
Old-Page, old-page/ עם תוספת נתיב, או בקשה עם ? שאינה חלק מה-url_from לא יתאימו אלא אם יש להם שורה משלהם. מחרוזת שאילתה בתוך url_from לעולם לא תתאים, כי הנתיב מופרד מהשאילתה לפני ההשוואה. הבדיקה של "האם הכתובת היא חיצונית" היא strpos($url_to, "http"): יעד פנימי שמכיל את http בכל מקום (למשל docs/http-codes) יטופל כחיצוני ויישלח בלי / בהתחלה.הליבה לא בודקת שהיעד אינו מפנה בחזרה. שתי שורות a => b ו-b => a יחזירו את הדפדפן ללולאה עד שהוא ייכשל. שרשרת a => b => c עובדת, אבל כל חוליה היא בקשה נוספת: עדיף להפנות ישירות ליעד הסופי. הסריקה של חבילת ה-SEO מזהה לולאות, שרשראות ויעדים ריקים בטבלה.
איפה זה נבדק ברצף הבקשה#
ההפניה נבדקת אחרי הניתוב וה-MODULE עוד לא רץ, אבל היא מגיעה רק אם הבקשה הגיעה ל-PAGE::load. שני דברים קודמים לה:
- מטמון עמודים מלא.
cache_engine::cache_php_checkרץ לפניPAGE::load. אם לכתובת הישנה כבר יש עותק ב-מטמון העמודים, הוא יוגש ישירות והשורה בטבלה לא תיבדק עד שהעותק יפוג או יימחק. אחרי שמוסיפים הפניה לכתובת שהייתה חיה, נקו את המטמון של הכתובת הזו (ניקוי ותחזוקה). - תשובות מוקדמות של הניתוב. נכסים סטטיים מ-
assets/,pjs.js,pg.jsודומיהם מוגשים ומסתיימים בתוךparse_friendly_url, לפני בדיקת ההפניות. כתובת שמתפרשת בשלבים האלה (או ש-die("router error")מסיים אותה) לא תופנה.
הפניה גוברת על קונטרולר: אם url_from זהה לנתיב של מודול קיים, המודול לא ירוץ.
ראו גם#
- ניתוב (ROUTER): הסדר המלא של ההחלטות
- כתובות ידידותיות (seoUrl)
- מטמון עמודים מלא
- חבילת ה-SEO: הבדיקות שמזהות שרשראות הפניה