SEO (רפרנס המחלקה)

רפרנס מלא למחלקה SEO: השדות הסטטיים, כל מתודה ציבורית עם חתימה והתנהגות מדויקת, סדר הפענוח של tags_summary, הטבלה seo_center, והחלקים הסמוכים (SeoVerification, PAGE::add_meta, PAGE::$robots).

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

המחלקה SEO (system/collections/SEO.php, api/core/collections/SEO.php בריפו) היא אוסף סטטי ששומר את תגיות ה-<head> של העמוד הנוכחי: כותרת, תיאור, מילות מפתח ו-Open Graph. הקונטרולר ממלא אותה לפני הרינדור, ו-PAGE::output() מדפיס אותה דרך SEO::tags_summary(). הדף הזה הוא הרפרנס של המחלקה; מה מפתח אתר צריך לעשות סביבה (canonical, robots, sitemaps, 404, JSON-LD) מופיע ב-SEO למפתחי אתר, והתגיות מנקודת מבט של העמוד ב-תגיות SEO ו-Schema.

מה מתועד כאן ומה לא

חבילת ה-SEO של ה-Market (סורק, ממצאים, IndexNow) היא מנוע נפרד ומתוארת ב-חבילת ה-SEO. המחלקה SEO היא רק שכבת התגיות של הליבה.

מחזור החיים בבקשה אחת#

  1. PAGE::load() קוראת ל-SEO::init() מיד אחרי PARAMS::init(): כל השדות מתאפסים למחרוזת ריקה.
  2. הקונטרולר קורא ל-SEO::set() / SEO::set_var() ול-SEO::set_key().
  3. PAGE::output() (רק בעמוד מלא, כלומר לא pmode=empg/inner) קוראת ל-SEO::tags_summary() בתחילת ה-<head> ומדפיסה את התוצאה, ובעמוד לקוח גם SEO::get_schema("WebPage").

משתנים סטטיים#

משתנהברירת מחדלמשמעות
SEO::$fieldsמערך עם og_url, meta_title, meta_description, meta_keywords, og_title, og_description, og_image (כולם "")הערכים שיודפסו. מפתח חדש שמוסיפים דרך set_var נכנס למערך ומודפס אף הוא
SEO::$title_include_sitenametrueהאם להוסיף ל-<title> את " - " ואחריו CONFIG::$platform_data["seo_title"]
SEO::$page_key""מפתח לחיפוש ב-CRM_seo_center עם is_by_url = 0
הערה
init() לא מאפסת את שני המשתנים האחרים SEO::init() מאפסת רק את ערכי $fields. $title_include_sitename ו-$page_key נשארים כפי שהוגדרו, אבל מכיוון שכל בקשה היא תהליך PHP חדש, זה משנה רק בהרצות ארוכות (CLI, cron).

SEO::init()#

static function init()

מאפסת כל ערך ב-SEO::$fields ל-"" (גם מפתחות שנוספו בזמן ריצה). נקראת על ידי PAGE::load(); אין סיבה לקרוא לה מקוד אתר.

SEO::set_key()#

static function set_key($key)

מציבה את SEO::$page_key. המפתח הוא כינוי לרשומה ב-CRM_seo_center עם is_by_url = 0 (למשל home או news_42), לפי מה שנכנס בשדה FormInput_SEO::$key בפאנל. אין מחזיר.

SEO::set(), SEO::set_var()#

static function set($fields, $value)       // כינוי: return self::set_var($fields, $value)
static function set_var($field, $value)    // אין ערך החזרה

שני הפרמטרים נקראים $fields / $field אבל מדובר בשדה אחד. הערך מועבר דרך המתג הבא (המפתחות הם שמות "קצרים", וחלקם כותבים לשני שדות):

$fieldנכתב אלעיבוד הערך
og_url, urlog_urlללא עיבוד
titlemeta_title ו-og_titlestrip_tags
descriptionmeta_description ו-og_descriptionstrip_tags, כיווץ רצפי רווחים לרווח אחד, trim
keywordsmeta_keywordsstrip_tags
og_image, imageog_imageמספר שלם (MISC::is_int): STORAGE::get_thumb($value, 1200, 627). אחרת כתובת כפי שהיא
כל מפתח אחר$fields[$field]ללא עיבוד: meta_title / meta_description / meta_keywords / og_title / og_description ישירות, og_type, author ועוד
// application/controllers/news.php
SEO::set("title", $row["title"]);
SEO::set("description", $row["summary"]);
SEO::set("image", (int)$row["image_id"]);              // מספר: נהפך לתמונה 1200x627
SEO::set("url", CONFIG::$site_url . "news/" . (int)$row["id"]);
SEO::set("og_type", "article");                        // מודפס כ-og:type
SEO::set_key("news_" . (int)$row["id"]);               // רשומת seo_center לפי מפתח
שמות מפתח &quot;מחוץ למערכת&quot; הופכים ל-meta

כל מפתח שלא מוכר נכנס ל-$fields ובסוף tags_summary מודפס כ-<meta name="<key>" content="..."> (קידומת meta_ נחתכת). שגיאת כתיבה (SEO::set("descripton", ...)) לא תיכשל, אלא תדפיס תגית descripton. גם עמודה לא צפויה בטבלת seo_center מגיעה לראש העמוד באותה דרך (ראו למטה).

SEO::tags_summary()#

static function tags_summary()    // מחזירה string של HTML

נקראת על ידי PAGE בלבד. הסדר:

  1. ברירות מחדל מהפלטפורמה. שדה ריק מקבל את seo_title, seo_description או seo_keywords מ-CONFIG::$platform_data. אם אין כותרת, SEO::$title_include_sitename מכובה כדי שהשם לא יודפס פעמיים.
  2. חיפוש ב-CRM_seo_center. המפתח הראשון הוא הנתיב: og_url (או REQUEST_URI כשהוא ריק), רק החלק של ה-path, בלי / בהתחלה ובסוף, אחרי urldecode, עם is_by_url = 1. אם לא נמצא וגם SEO::$page_key לא ריק: לפי page_key עם is_by_url = 0.
  3. דריסה מהרשומה. כל עמודה לא ריקה ברשומה עוברת set_var ודורסת את מה שהקונטרולר קבע. עמודות מבניות מדולגות (id, page_key, is_by_url, ord, title_include_sitename, platform_id, lang, is_active, date_created, date_updated, created, updated), ו-title_include_sitename נקרא רק כשיש meta_title ברשומה. scripts מוזרק ל-PAGE::add_meta(). og_image/image ברשומה הוא מספר קובץ (> 0) ונפתר ל-STORAGE::get_by_name($val, "wide", 1200, 627).
  4. הדפסה. קודם <meta name="twitter:card" content="summary_large_image">, אחריה תגית האימות של Search Console (ראו SeoVerification), ואז כל שדה לא ריק לפי הטבלה:
שדהפלט
meta_title<title> עם הערך הגולמי (" - " . seo_title נוסף כש-$title_include_sitename)
og_titleog:title ו-twitter:title
og_descriptionog:description ו-twitter:description
og_imageog:image ו-twitter:image
og_typeog:type ו-twitter:type
og_urlog:url ו-twitter:url
כל שדה אחר<meta name="<key ללא meta_>" content="...">, כלומר meta_description מודפס כ-<meta name="description">

כל הערכים חוץ מ-<title> עוברים htmlspecialchars.

מלכודות ב-tags_summary

(1) <title> מודפס בלי htmlspecialchars (רק strip_tags כשהוגדר דרך set_var), ולכן & בכותרת לא מקודד. (2) og_url מודפס רק כשהוגדר במפורש: הליבה לא ממלאת אותו מ-REQUEST_URI. (3) החיפוש ב-seo_center בלי platform_id ו-lang: באתר רב-פלטפורמות אותו נתיב מקבל אותו meta בכל הדומיינים. (4) 1 עד 2 שאילתות seo_center בכל רינדור, ללא מטמון. (5) כל עמודה לא מוכרת בטבלה נשפכת כ-<meta name=...>, לכן אל תוסיפו עמודות עזר ל-seo_center בלי להוסיף אותן לרשימת הדילוג.

SEO::get_schema()#

static function get_schema($type)    // "WebPage" | "Organization" | "NewsArticle"

מחזירה מחרוזת <script type="application/ld+json">...</script>. סוג לא מוכר מחזיר תגית עם [].

$typeמה נבנה
WebPage@context, @type: WebPage, @id = CONFIG::$site_url. זו הקריאה היחידה שהליבה עושה בעצמה, בכל עמוד לקוח
Organizationname = seo_title של הפלטפורמה, url, ו-logo קבוע
NewsArticleheadline = meta_title הנוכחי, ושדות image, author, datePublished, dateModified, publisher.logo קבועים
Organization ו-NewsArticle מכילים נתוני דמו של אתר אחר

שני הסוגים מדפיסים לוגו מ-rcs.mako.co.il, מחבר "משה משה" (בשדה url של Person) ותאריכים קבועים 2021-12-12. אל תקראו להם באתר חי: זה structured data שקרי. בנו JSON-LD בעצמכם והזריקו אותו עם PAGE::add_meta() (דוגמה מלאה ב-SEO למפתחי אתר). רק WebPage בטוח לשימוש.

החלקים הסמוכים#

PAGE::add_meta(), print_meta_tags()#

public static function add_meta($val, $area = "head")
public static function print_meta_tags($area = "")

add_meta מוסיפה מחרוזת HTML גולמית (תגית <meta>, <link>, <script>) לאזור (head כברירת מחדל). print_meta_tags מדפיסה לפי אזור. שימו לב: ערך שמוזרק כך אינו עובר escaping, ולכן כל נתון שמגיע ממשתמש חייב לעבור htmlspecialchars לפני ההזרקה. פרטים ב-PAGE: נכסים, מטא ואירועים.

PAGE::add_meta('<link rel="canonical" href="' . htmlspecialchars(CONFIG::$site_url . "news/" . (int)$row["id"], ENT_QUOTES) . '">');

PAGE::$robots#

מחרוזת, ברירת מחדל "ALL", מודפסת בכל עמוד ב-<meta name="ROBOTS" content="..."> מיד אחרי תגיות head:

PAGE::$robots = "noindex, follow";

SeoVerification::meta_tag()#

public static function meta_tag(): string    // system/libraries/SeoVerification.php

מחזירה <meta name="google-site-verification" content="..."> מהטוקן ששמור בפרמטר של CRM_params, או מחרוזת ריקה כשאין טוקן. tags_summary קוראת לה בתוך try/catch, בכל עמוד ולא רק בדף הבית, ושגיאה בה לא פוגעת בעמוד. הטוקן נקרא ב-SELECT ישיר מהטבלה, לא דרך PARAMS, כך שהוא נכנס לתוקף מיד אחרי שמירה (אבל עמוד שנשמר במטמון לא יציג אותו, ראו מטמון עמודים מלא).

רשומות seo_center#

הטבלה CRM_seo_center נערכת בפאנל /{admin}/seo_center ובשדה FormInput_SEO. עמודות הליבה:

עמודהסוגמשמעות
idINT PK
page_keyVARCHAR(255)הנתיב (כש-is_by_url = 1) או המפתח שהוגדר ב-SEO::set_key
is_by_urlTINYINT(1)1 מחפש לפי נתיב הבקשה, 0 לפי SEO::$page_key
meta_title, title_include_sitenameVARCHAR(255), TINYINT(1)כותרת, והאם להוסיף שם אתר
meta_description, meta_keywordsTEXT
og_title, og_descriptionVARCHAR(255), TEXT
og_imageINTמזהה קובץ בטבלה storage
ordINTסדר בפאנל

אתר שמקים מסד חדש חייב ליצור אותה (DDL ב-SQL להקמה). ראו גם סכמת הטבלאות.

// הוספת רשומת SEO לדף הבית בלי הפאנל (לא להריץ על אתר חי בלי לבדוק קודם שאין רשומה)
$ins = DB::update("seo_center");
$ins->set_var("page_key", "home");
$ins->set_var("is_by_url", 0);
$ins->set_var("meta_title", "Wizzo - הבית");
$ins->set_var("meta_description", "תיאור קצר לדף הבית");
$ins->insert();

דף NEWPAGE#

הקונטרולר newpage_public (דפי נחיתה מ-NEWPAGE) משתמש ב-SEO::set_var("title", ...) וב-SEO::set_var("description", ...) מנתוני head של השירות. את og:image ואת noindex הוא מוסיף ישירות ב-PAGE::add_meta(), לא דרך SEO::$fields.

ראו גם#

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