תפיסת Exceptions ב-PHP

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

לא מזמן, בעקבות מאמר אחר שבו כתבתי על cURL, כתבתי מאמר על try-catch ומיד חטפתי (שוב) קיתונות של רותחין (שוב) על למה לא פירטתי על Exceptions ב-PHP. אז אולי המאמר הזה הוא הזדמנות מצוינת לדבר קצת על Exceptions.

Exceptions הם ה-דרך שלנו לדווח על טעויות שונות ומשונות והן מאד מאד שימושיות בשלב הפיתוח ולאחריו. באופן עקרוני, Exception מדווח לנו על תקלות ובעיות שונות בקוד – למשל חוסר הצלחה בחיבור לשירות כלשהו, קלט שלא מתאים למצופה ושלל בעיות נוספות.

בואו ונדגים באמצעות דוגמה מ-php.net, אני אצור פונקציה שמה שהיא עושה זה להחזיר את המספר ההופכי – למשל אם אני דוחף לפונקציה 2, אני אקבל 1/2, אם אני אדחוף לפונקציה 3, אני אקבל 1/3 וכך הלאה.

וכך הפונקציה נראית:


<?php
function inverse($x) {
	return 1/$x;
}

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


<?php
function inverse($x) {
	return 1/$x;
}

inverse(0);

יניב לי אזהרת PHP לא סימפטית במיוחד:

שגיאת PHP המתקבלת כתוצאה מחילוק באפס
שגיאת PHP המתקבלת כתוצאה מחילוק באפס

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

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


< ?php
function inverse($x) {
    if (!$x) {
        print 'Number is zero!!!! ahhhh!';
		return 'n/a';
    }
    else return 1/$x;
}

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

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

דרך השימוש היא פשוטה ביותר – שימו לב!


<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    else return 1/$x;
}

inverse(0);

מה יקרה אם אני אריץ את הקוד הזה? ברגע שתתרחש התקלה ה-Exception יקפיץ fatal error וירשום את ההודעה שהגדרנו לו:

תקלת PHP שנובעת מ-Exception
תקלת PHP שנובעת מ-Exception

'רגע אחד!' חלק מכם בטח אומרים 'מה זה fatal error??? אז בשביל מה אני צריך את זה בכלל???' בדיוק בשביל זה יש את ה-try catch! אם אני מכניס את זה לתוך try-catch, אז אין לי fatal error אלא משהו אחר לגמרי – הנה דוגמה!


< ?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

התוצאה המתקבלת:
Caught exception: Division by zero.

נחמד, לא?
במאמר על try-catch הזהרתי לא להשתמש במבנה הזה בלי הכרה, אפשר להנות מיתרונות ה-Excpetion בלי fatal error ובלי try-catch. איך עושים את זה? באמצעות הכרזה על פונקציה שמטפלת ב-exceptions ובכל פעם שנזרוק exception הפונקציה הזו תרוץ. למשל:


<?php
function customException($e) {
	echo 'Caught exception: ',  $e->getMessage(), "\n";
}
set_exception_handler('customException');

function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    else return 1/$x;
}

 echo inverse(0);

יש עוד לא מעט בנושא Exceptions, אלו מכם שמתכנתים בגישה מונחית עצמים, ישמחו לדעת שיש class שלם של exceptions שאפשר לרשת ממנו ולעשות איתו דברים מופלאים – כמו להגדיר סוגים שונים של Exceptions – אבל זהו הבסיס. אם לא השתמשתם עד כה ב-exceptions, כדאי לחשוב איך להשתמש בו וליצור סקריפטים יציבים וחזקים יותר.

פוסטים נוספים שכדאי לקרוא

רספברי פיי

הרצת גו על רספברי פיי

עולם הרספברי פיי והמייקרים ניתן לתפעול בכל שפה – לא רק פייתון או C – כאן אני מסביר על גו

DALL·E 2024-09-06 12.34.24 - A visually engaging post about Python and cryptographic problems. The image should feature a dark-themed background with a glowing, futuristic Python
פתרונות ומאמרים על פיתוח אינטרנט

בעיות במימוש של פונקציות קריפטוגרפיות בפייתון

היום (16 לספטמבר) ממש, אני מעביר הרצאה ב-PyconIL 2024 על בעיות קריפטוגרפיות באפליקציות פייתון. לצערי אי אפשר להכניס את כל הבעיות הקריפטוגרפיות להרצאה אחת או

רספברי פיי

התקנת OpenCanary על רספברי פיי

מה זה OpenCanary ואיך אפשר להתקין אותה על רספברי פיי ולשדרג את אבטחת הרשת הביתית או המשרדית.

גלילה לראש העמוד