MasterScripter

אקספקטו פטרונום: 7 מתודות קסם ששווה להכיר

החל מגרסה 5, PHP מציעה תמיכה מלאה-יותר (אך לא מלאה) של עקרונות תכנות מונחה עצמים,
כשאחת התכונות החדשות שנוספו היא Magic Methods – גם אם לא שמעתם עד היום על המונח הזה, אני מבטיח לכם שיצא לכם ליישם פונקציה שכזו עשרות פעמים!


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

מתודות קסם? Magic Methods? מה אתה רוצה מחיינו?!

אני מתנצל מעומקי ליבי אם אני מאכזב מי מקוראיי, אבל אין קסם ב – PHP (לפחות עוד לא הוכח..), והכוונה במתודות קסם היא לפונקציות מחלקה שמורות (נכון לכתיבת הפוסט יש כ – 15 כאלה), שנקראות אוטומטית במצבים מסויימים.
אפשר להקביל אותן ל – Event Listeners ב – JavaScript, אם כי הקונספט לא זהה.

כל Magic Method מתחילה עם מקדם __ (שני קווים תחתונים) ולא מומלץ* ליצור Magic Methods חדשות.
* אמנם אין הגבלה טכנית על יצירת פונקציות שמתחילות ב – __, אך יצירת פונקציות כאלו יוצרת סיכון להתנגשות עם גרסאות עתידיות של PHP.

Magic Methods מאפשרות לנו לשלוט על הדרך שבה מחלקה תתמודד עם אירוע מסויים, כמו קריאה לתכונה ($obj->property), התייחסות לאובייקט כמחרוזת (echo $obj) ועוד.
הן טומנות בחובן כוח גדול מאד – שימוש מושכל ונכון בהן יכול לחסוך לנו הרבה שורות קוד ולייעל את העבודה שלנו ואת הסקריפט. סקרנתי אתכם? בואו נצא לדרך ונסקור 7 Magic Methods:

__construct() ו – __destruct()

(החל מגרסה 5)

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

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

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

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

__sleep() ו – __wakeup()

(החל מגרסה 4)

המתודה __sleep מבוצעת בעת קריאה לפונקציה serialize() ולכן חשוב להבין מה הפונקציה עושה, כדי להבין את תפקיד המתודה:
הפונקציה serialize() מקבלת פרמטר מכל סוג שהוא למעט Resource ומחזירה ערך מומר למחרוזת שמייצגת את הפרמטר ומכילה בתוכה פירוט על סוג הנתונים והערכים שהפרמטר הכיל.
זו דרך נפוצה לשמור מידע באופן חסכוני. כך לדוגמה, ב – Codeigniter 2, נתוני ה – Session של כל משתמש עוברים סריאליזציה ונשמרים בדטבייס כמחרוזת.

ניקח את הדוגמה הבאה, שמתארת סריאליזציה של אובייקט מסוג DB:

הערך שיודפס:

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

לצורך הדוגמה, אנו רוצים להעביר אך ורק את ה – id של המשתמש ואת ה – profile שלו, ללא המערך שמפרט אילו הרשאות יש לו:

הערך שיודפס:

(לא באמת) קסם! ההתייחסות למערך access נעלמה כלא הייתה 🙂

ואם serialize() מפעילה את __sleep(), אז מה קורה כשנקרא לפונקציה unserialize()?
מתודת הקסם __wakeup() תופעל
רק בשביל שאהיה רגוע שלכל הקוראים זה ברור – הפונקציה unserialize() לוקחת מחרוזת שנוצרה מפונקציית serialize() וממירה אותה בחזרה לערך PHP.

__toString()

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

כאשר נתייחס למחלקה כמחרוזת, לדוגמה ננסה להדפיסה, נקבל את השגיאה הבאה:

Catchable fatal error: Object of class Student could not be converted to string

בואו נשדרג את המחלקה עם מתודת הקסם __toString:

ועכשיו, במקום השגיאה הפטאלית ממקודם, נקבל הפעם את הציון המשוקלל של התלמיד:

שני קווים מנחים לשימוש בפונקציה:

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

העמסה

(באנגלית: overloading)

בשפות רבות שמיישמות תכנות מונחה עצמים, המושג העמסה משמעותו יצירת מס' מתודות בעלות שם זהה, אך חתימה שונה.
למשל, דוגמה מהשפה Java:

בדוגמה הזו, קטע הקוד מאפשר לקרוא לפונקציה myMethod גם עם פרמטר אחד וגם עם שניים, ולטפל באופן שונה בכל אחד מהמצבים.
לעומת זאת, ב – PHP המושג 'העמסה' מקבל משמעות שונה לגמרי, ומתייחס לפונקציות שמאפשרות לנו להגדיר תהליך לקריאת נתוני משתנים וקריאה לפונקציות באופן דינמי, או יצירת/מחיקת משתנים באופן דינמי.
מה הכוונה באופן דינמי? ניקח למשל את הדוגמה הבאה, שבה נוצר משתנה מחלקה באופן דינמי:

שתי מתודות הקסם הבאות עליהן אפרט 'רשומות' תחת המונח העמסה.
הפונקציות הללו נקראות (רק אם הוגדרו) כאשר נעשה שימוש בתכונות / פונקציות מחלקה לא זמינות*.

*  הגדרה: תכונת / פונקציית מחלקה לא זמינה היא תכונה / פונקצייה שטרם הוכרזה או לא נגישה במרחב (scope) הנוכחי.
לדוגמה, קריאה לתכונת מחלקה מוגנת (protected) מחוץ למחלקה:

מתודות הקסם הבאות נחשבות למתודות העמסה, וככאלה נדרשות להיות מוגדרות כציבוריות (public), ואין להעביר פרמטרים בהפניה (&):

  • __callStatic() (החל מגרסה 5.3.0) – מופעלת בקריאה לפונקציית מחלקה סטטית
  • __call() (החל מגרסה 5.0.0) – מופעלת בקריאה לפונקציה
  • __isset() (החל מגרסה 5.1.0) – מופעלת בקריאה לפונקציה isset
  • __unset() (החל מגרסה 5.1.0) – מופעלת בקריאה לפונקציה unset
  • __set() ו – __get() – פירוט בפסקה הבאה

חשוב לי להביא את דעתי האישית – מתודות קסם בכלל והעמסה בפרט לא נדרשים עבור כל מחלקה.
סומך עליכם שתעשו שימוש מושכל ולא סתמי!

 

__set ו – __get

מתודות הקסם נקראות כאשר מנסים ליישם  (__set) או לקרוא  (__get) ערך ל/מ תכונה לא זמינה.

שימוש בסיסי וקלאסי ב – __set מתרחש במחלקה בה הוספת תכונות באופן דינמי הינה דבר שבשגרה,
וכדי למנוע התנגשות עם תכונות מחלקה מוגדרות מראש, ננתב את את כל התכונות שהוגדרו דינמית למערך ייעודי:

שימו לב לאזהרה שקיבלנו: לא קיימת תכונה בשם $name!
אבל אנחנו יודעים שהיא קיימת במערך $dynamicProperties, שהוא מערך שלא ניתן לגשת אליו מחוץ למרחב המחלקה.
אז מה עושים? ניחשתם נכון! __get בא לעזרתנו:

עוד קצת על קסמים..

הפוסט הגיע לסיומו, אני מקווה שהעשרתי את הידע שלכם כמפתחי PHP ושמעתה תהפכו למאסטרים של Magic Methods.
במקורות (תכף, ממש מתחת) יש קישור לתיעוד הרשמי באתר של PHP, שם תוכלו לקרוא על כל מתודות הקסם הקיימות.

וכדי שלא ארגיש אשם על כך שיצאתם מפה ללא קסמים אמיתיים, אגלה לכם קסם שלא הרבה שמעו עליו. אבל תבטיחו לי שלא תגלו!
כל מי שמקליד את כתובת המייל שלו בטופס למטה, יקבל תכנים סופר-איכותיים ואקסקלוסיביים ישר לתיבת הדואר הנכנס!
שווה, לא?

מקורות

  1. רשימת פונקציות והסבר – תיעוד רשמי באתר השפה
  2. העמסה – תיעוד רשמי באתר השפה

 

אם הגעת עד לפה, הגיע הזמן להירשם לניוזלטר!

Summary
Article Name
Magic Methods ב- PHP
Description
פירוט והסבר אודות הרעיון מאחורי והשימוש ב7 Magic Methods ב- PHP ששווה להכיר.
Author
Publisher Name
MasterScripter
Publisher Logo
אודות 
hello world! אני יונתן, מתעסק בתכנות ופיתוח WEB פלוס מינוס מאז שאני זוכר את עצמי. ב2013 הקמתי את קבוצת סיזן ביחד השותף היקר שלי - שלומי שלומקה זק. ביום מתעסק בפיתוח ועיצוב אתרי אינטרנט ואפליקציות, עיצוב חוויית משתמש, הקמת מיזמים, ועוד..אבל מה שלא ידעתם עליי - זה שבלילה אני באטמן. אל תגלו לאף אחד!

7 תגובות

  1. אהוד

    13 בינואר 2017 - 13:59
    תגובה

    יפה מאד. תודה
    אני באופן אישי מנסה לברוח מ PHP כ OOP.
    זה היופי שבשפה הזו לדעתי – היכולת לכתוב קוד צד שרת בתכנות פרוצדורלי.
    לא אכפת לי שהמגמה בעולם הפוכה.

    • יונתן נקסון

      13 בינואר 2017 - 14:54
      תגובה

      בתור אחד שמתרחק מתכנות פרוצדורלי,
      מעניין אותי לדעת האם ואיך אתה מצליח לשמור על סדר בקוד שלך?

    • מאיר

      14 בינואר 2017 - 19:26
      תגובה

      סליחה אבל, אין לך מושג כמה אתה טועה…

  2. אמיר סימן טוב

    13 בינואר 2017 - 14:48
    תגובה

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

    • יונתן נקסון

      13 בינואר 2017 - 21:21
      תגובה

      קבל הרחבה בנושא העמסה.
      האם עכשיו זה כתוב ברור יותר?

  3. עידו

    29 בספטמבר 2023 - 17:27
    תגובה

    תודה רבה מוסבר ממש טוב עזר לי מאדד

  4. הדס

    29 בספטמבר 2023 - 17:28
    תגובה

    תודה רבה מוסבר ממש טוב עזר לי מאדדד

השאר/י תגובה ליונתן נקסון

לבטל

האימייל לא יוצג באתר. שדות החובה מסומנים *