כדי להציג שגיאות PHP, שימו את השורות האלה בראש הסקריפט: ini_set('display_errors', '1'); ו-error_reporting(E_ALL);. הראשונה גורמת ל-PHP להדפיס הודעות שגיאה, והשנייה גורמת לה לדווח על כל סוג של שגיאה, כולל אזהרות והודעות deprecation.
<?php
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
כשזה במקום, טעות כמו קריאת משתנה שלא הוגדר מעולם מדפיסה הודעה עם הקובץ ומספר השורה במקום להיכשל בשקט:
Warning: Undefined variable $total in /home/index.php on line 7
error_reporting() שנקראת בלי ארגומנט מחזירה את ההגדרה הנוכחית כמספר. לחצו על Run כדי לקבוע רמה ולפענח אותה בחזרה לשמות:
כל סוג שגיאה הוא ביט אחד, ולכן E_ALL & ~E_DEPRECATED פירושו "הכול חוץ מ-deprecations". שנו את השורה הראשונה ל-error_reporting(E_ERROR | E_WARNING); והריצו שוב.
הצגת שגיאות ב-php.ini
הגדרה בתוך הסקריפט חלה רק אחרי שהסקריפט מתחיל לרוץ. כדי להציג שגיאות בכל סקריפט, כולל שגיאות תחביר, שנו את php.ini (מצאו אותו עם php --ini):
; Development
display_errors = On
display_startup_errors = On
error_reporting = E_ALL
הפעילו מחדש את Apache או את PHP-FPM אחרי העריכה. השרת המובנה php -S ושורת הפקודה קוראים את הקובץ בכל הפעלה. באחסון משותף בלי גישה ל-php.ini, Apache עם mod_php מקבל גם שורות ב-.htaccess:
php_flag display_errors on
php_value error_reporting -1
-1 מדליק את כל הביטים, וזה אותו דבר כמו E_ALL.
רמות השגיאה
| קבוע | מה מפעיל אותו | עוצר את הסקריפט |
|---|---|---|
E_ERROR | שגיאת זמן ריצה פטאלית, כמו חוסר בזיכרון | כן |
E_PARSE | שגיאת תחביר בקובץ | כן |
E_WARNING | משתנה או מפתח מערך לא מוגדרים, קובץ חסר ב-include | לא |
E_NOTICE | בעיות קטנות (מעטות נשארו ב-PHP 8) | לא |
E_DEPRECATED | קוד שגרסת PHP עתידית תדחה | לא |
E_USER_* | שגיאות שאתם מעלים עם trigger_error() | רק E_USER_ERROR |
E_ALL | כל הרמות, כולל שגיאות ליבה והידור שלא מופיעות כאן |
PHP 8.0 הפכה הרבה אזהרות ישנות לחריגות: חלוקה באפס עם / והעברת טיפוס שגוי לפונקציה מובנית זורקות עכשיו תת מחלקה של Error, בדיוק כמו קריאה לפונקציה לא מוגדרת מאז PHP 7. אפשר לתפוס את שלושתן:
חריגות מוסברות בtry ו-catch. אזהרות, notices ו-deprecations עדיין עוברות דרך מערכת דיווח השגיאות שמתוארת כאן.
רישום שגיאות ללוג במקום להציג אותן
באתר חי, מבקרים לעולם לא צריכים לראות הודעות שגיאה: הן חושפות נתיבים, SQL וקוד. כתבו אותן לקובץ לוג במקום:
; Production
display_errors = Off
log_errors = On
error_log = /var/log/php/app-errors.log
error_reporting = E_ALL
השאירו error_reporting = E_ALL בייצור. הורדת הרמה לא גורמת לשגיאות להיעלם, היא רק מונעת מכם לשמוע עליהן. ההודעות שלכם יכולות להגיע לאותו לוג עם error_log():
<?php
error_log("Payment failed for order 1042");
אחר כך עקבו אחרי הקובץ בזמן הבדיקות: tail -f /var/log/php/app-errors.log.
הפיכת אזהרות לחריגות עם set_error_handler
set_error_handler מחליפה את הטיפול הרגיל של PHP באזהרות, notices ו-deprecations בפונקציה משלכם. דפוס נפוץ ממיר כל אחת מהן ל-ErrorException, כך שמפתח מערך שנשכח עוצר את הקוד כמו כל חריגה אחרת ואפשר לתפוס אותו:
ה-handler מקבל את רמת השגיאה כארגומנט הראשון, כך שהוא יכול לטפל ברמות שונות בצורה שונה. הזה רק רושם deprecations ללוג והופך את כל השאר לחריגה:
שגיאות פטאליות ושגיאות תחביר אף פעם לא מגיעות ל-handler, כי הסקריפט לא יכול להמשיך אחריהן. כדי לרשום אותן, רשמו פונקציית shutdown שקוראת את error_get_last().
קריאת השגיאה האחרונה עם error_get_last
חלק מהפונקציות מחזירות false ומדווחות על הסיבה רק כאזהרה, למשל file_get_contents על קובץ חסר. error_get_last() מחזירה את האזהרה הזו כמערך, וזה שימושי כשרוצים להציג הודעה משלכם:
האופרטור @ לפני הקריאה משתיק את ההודעה עבור הביטוי הזה בלבד. השתמשו בו במשורה ורק כשאתם בודקים את התוצאה מיד אחר כך, כמו כאן; @ לבדו רק מסתיר באגים.
טעות נפוצה: הצגת השגיאות פעילה, אבל הדף עדיין ריק
אם הוספתם ini_set('display_errors', '1') ועדיין רואים דף לבן, השגיאה היא כנראה שגיאת תחביר. PHP מנתחת את כל הקובץ לפני שהיא מריצה את השורה הראשונה, כך ש-; או } חסרים עוצרים הכול לפני ש-ini_set רצה. בדקו את הקובץ מהטרמינל, שתמיד מדפיס את ההודעה:
php -l index.php
Errors parsing index.php
PHP Parse error: syntax error, unexpected token "," in index.php on line 2
מספר השורה מצביע על המקום שבו PHP הרימה ידיים, ולעיתים קרובות זו השורה שאחרי הטעות האמיתית. תקנו, הריצו שוב php -l עד שיופיע No syntax errors detected, ואז טענו מחדש את הדף.
שאלות נפוצות
איך מציגים את כל השגיאות ב-PHP?
הוסיפו ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); error_reporting(E_ALL); בראש הסקריפט ממש, או הגדירו display_errors = On ו-error_reporting = E_ALL ב-php.ini והפעילו מחדש את שרת הווב או את PHP-FPM.
למה דף ה-PHP שלי מציג מסך לבן ריק?
שגיאה פטאלית עצרה את הסקריפט בזמן ש-display_errors כבויה, ולכן שום דבר לא הודפס. הפעילו את הצגת השגיאות (או קראו את לוג השגיאות, למשל עם tail -f על הקובץ ש-error_log מצביע עליו) כדי לראות את ההודעה ואת מספר השורה.
למה ini_set('display_errors', 1) לא מציגה את שגיאת התחביר שלי?
שגיאת תחביר עוצרת את PHP לפני שאף שורה בקובץ רצה, כך שהקריאה ל-ini_set אף פעם לא מתבצעת. הגדירו את display_errors ב-php.ini, או שימו את ini_set בקובץ קטן שעושה include לקובץ השבור.
האם display_errors צריכה להיות פעילה בסביבת ייצור?
לא. הודעות שגיאה חושפות למבקרים נתיבי קבצים ופרטי קוד. בייצור השתמשו ב-display_errors = Off, ב-log_errors = On ובנתיב error_log, והשאירו error_reporting = E_ALL כדי שבעיות עדיין יירשמו.
מה עושה error_reporting(0)?
היא מכבה את הדיווח על כל סוגי השגיאות עד סוף הסקריפט, כך שאזהרות ואפילו שגיאות פטאליות לא מציגות שום הודעה. היא מסתירה בעיות במקום לתקן אותן; עדיף לרשום שגיאות ללוג מאשר להשתיק אותן.