اولین باری که لاگ خطای یک سایت را باز کردم و پر بود از خطای PHP Notice، فکر کردم سایت در حال فروپاشی است. اما سایت داشت کار می‌کرد، فقط لاگ چند صد مگابایتی شده بود. دقیقاً همان‌جا یاد گرفتم خطای Notice بدترین نوع خطا نیست؛ خبرچین‌ترین نوع خطاست. اگر درست خوانده شود، جای باگ‌های پنهان را نشان می‌دهد، و اگر نادیده گرفته شود، آرام‌آرام به Warning و بعد به Fatal error تبدیل می‌شود. در این راهنما همان مسیری را می‌گویم که برای پاکسازی Noticeها طی می‌کنم.

Notice در PHP دقیقاً چیست؟

در PHP سه سطح اصلی خطا داریم: Notice، Warning و Fatal error. Notice پایین‌ترین سطح است و معنایش این است: «کد اجرا شد، ولی احتمالاً چیزی این‌جا درست نیست». مثلاً دسترسی به یک متغیر تعریف‌نشده، دسترسی به ایندکس ناموجود یک آرایه، یا استفاده از مقدار null به‌عنوان شیء. این سه، در نگاه اول کوچک به نظر می‌رسند ولی همه‌شان نشانهٔ یک فرض غلط در منطق برنامه‌اند.

Notice، فریاد نمی‌زند؛ فقط زیر لب چیزی می‌گوید که اگر بشنوید، جلوی فاجعه را می‌گیرد.

در نسخه‌های جدید PHP — به‌خصوص PHP 8 — سطح‌بندی خطاها دقیق‌تر شده. آن‌چه قبلاً Notice حساب می‌شد، در بعضی موارد حالا Warning است. مثلاً Undefined variable و Undefined array key هنوز در دستهٔ E_WARNING قرار می‌گیرند؛ ولی Undefined constant که قبلاً Notice بود، در PHP 8 به Error تبدیل شده و کد را متوقف می‌کند. این تغییر به‌نفع کیفیت کد است، ولی کدهای قدیمی را غافلگیر می‌کند.

تفاوت Notice، Warning و Fatal error

برای این‌که بدانید هر خطا چقدر جدی است، جدول زیر را در کارم زیاد استفاده می‌کنم:

سطحمعنااجرای کد
E_NOTICEاحتمال اشتباه منطقی در متغیر یا آرایهادامه می‌یابد
E_WARNINGمشکل جدی‌تر مثل فایل بازنشده یا پارامتر نامعتبرادامه می‌یابد ولی با ریسک
E_ERROR / Fatalتوقف کامل کدمتوقف می‌شود
E_DEPRECATEDتابع یا رفتار قدیمی که در نسخه‌های بعدی حذف می‌شودادامه می‌یابد

در پست‌های جداگانه‌ای که نوشته‌ام، هم خطای Warning در PHP را باز کرده‌ام و هم خطای Fatal error را. تفاوت این سه را وقتی بفهمید، تشخیص سرعت‌تان چند برابر می‌شود.

Noticeها از کجا می‌آیند؟

در ۹۰٪ مواقعی که Notice می‌بینم، ریشه در یکی از این چند الگو است:

  • متغیر تعریف‌نشده: کد به $foo دسترسی دارد بدون اینکه جایی تعریفش کرده باشد. جزئیات بیشتر در رفع خطای Undefined variable در PHP.
  • ایندکس ناموجود آرایه: مثل $_POST["email"] وقتی کاربر فیلد ایمیل را نفرستاده.
  • مقدار null در جای شیء: نتیجهٔ یک کوئری که ردیفی برنگردانده ولی کد بی‌گدار ->field صدا می‌زند.
  • توابع Deprecated: استفاده از توابعی که در نسخه‌های جدید PHP منسوخ شده‌اند. توضیح کامل در خطای Deprecated در PHP.
  • افزونه‌ها یا قالب‌های قدیمی: کدی که برای PHP 5 نوشته شده و امروز روی PHP 8 اجرا می‌شود.

نمایش یا نمایش ندادن: تصمیم مهم هر پروژه

یک تصمیم ساده وجود دارد که در پروژه‌های واقعی خیلی سرنوشت‌ساز است: آیا Noticeها به کاربر نمایش داده شوند یا نه؟ سه حالت عملی:

  • محیط توسعه (development): همه خطاها نمایش داده می‌شوند. این حالت تنها حالتی است که می‌شود Noticeها را دید و اصلاح کرد.
  • محیط staging: نمایش خاموش، ولی لاگ روشن.
  • محیط تولید (production): نمایش خاموش، لاگ روشن، و error_reporting طوری تنظیم شده که فقط خطاهای جدی ثبت شوند.

این سه‌گانه را در wp-config.php یا در فایل php.ini تنظیم می‌کنم:

// Development
ini_set("display_errors", 1);
ini_set("display_startup_errors", 1);
error_reporting(E_ALL);

// Production
ini_set("display_errors", 0);
ini_set("log_errors", 1);
error_reporting(E_ALL & ~E_DEPRECATED & ~E_NOTICE);

در وردپرس، ثابت‌های WP_DEBUG، WP_DEBUG_LOG و WP_DEBUG_DISPLAY همین کار را انجام می‌دهند. نکتهٔ مهم: هیچ‌وقت روی سایت زنده با WP_DEBUG_DISPLAY = true کار نکنید؛ یک Notice می‌تواند به کاربر پیام مسیر فایل‌ها را نشان بدهد.

مسیر اصلاح: از خواندن تا پاکسازی

روش من، چهار گام ساده دارد:

  1. خواندن لاگ با فیلتر: در فایل debug.log وردپرس، فقط خطوط Notice را با grep Notice جدا کنید.
  2. گروه‌بندی بر اساس فایل: Noticeها را بر اساس مسیر فایل گروه کنید. اگر بیشترشان از یک افزونه می‌آید، اول سراغ آن بروید.
  3. اصلاح از ریشه: هر Notice را با افزودن isset() یا ?? سرکوب نکنید — سعی کنید بفهمید چرا آن متغیر تعریف نشده. اگر واقعاً اختیاری است، مقدار پیش‌فرض منطقی بدهید.
  4. تست پس از هر اصلاح: بعد از تغییر، همان مسیر را در staging تست کنید تا مطمئن شوید چیزی نشکسته.
سرکوب کردن Notice با @ یا با تنظیم error_reporting، مثل بستن چراغ خطر ماشین است؛ ماشین همان خرابی را دارد، فقط دیگر نمی‌بینید.

گاهی Notice در جایی می‌آید که باگ واقعی نیست؛ مثلاً یک افزونه کار خودش را می‌کند ولی لاگ را پر می‌کند. در این حالت، به‌جای خاموش کردن کل لاگ، فقط همان فایل را از دامنهٔ گزارش خارج کنید. اگر خطا همزمان با کندی سایت بود، مسیر عیب‌یابی را در عیب‌یابی سرعت سایت دنبال کنید؛ Noticeها به‌تنهایی سایت را کند نمی‌کنند، ولی نشانهٔ کدی هستند که ممکن است کند باشد.

در وردپرس با Noticeها چه کنیم؟

وردپرس خودش با PHP 8 سازگار است، ولی اکوسیستم افزونه‌ها و قالب‌ها همیشه عقب‌تر می‌ماند. سه توصیهٔ عملی:

  • افزونه‌های نال و قدیمی را حذف کنید: رایج‌ترین منبع Notice در سایت‌های فارسی، افزونه‌های دست‌کاری‌شده‌ای هستند که برای PHP 5 نوشته شده‌اند.
  • افزونهٔ Debug مخصوص وردپرس نصب کنید: افزونه‌هایی که Noticeها را داخل پیشخوان وردپرس نشان می‌دهند، بسیار راحت‌تر از خواندن فایل لاگ هستند.
  • پیش از ارتقای PHP، در staging تست کنید: ارتقای PHP از ۷.۴ به ۸.۲ یکی از رایج‌ترین دلایل انفجار Noticeها در سایت‌های قدیمی است.

اگر خطاهای PHP در سایت شما زیاد شده‌اند و حتی سایت سفید می‌شود، راهنمای رفع صفحهٔ سفید در وردپرس مسیر نجات را نشان می‌دهد.

اشتباهات رایج

  • خاموش کردن کورکورانه لاگ: مشکل را پنهان می‌کند ولی در پس‌زمینه ادامه دارد.
  • سرکوب با @: این کار سرعت اجرا را کمی هم کاهش می‌دهد و جلوی دیدن خطای اصلی را می‌گیرد.
  • اصلاح همه Noticeها یک‌جا: ممکن است کد سالم را خراب کنید. یکی‌یکی، با تست، اصلاح کنید.
  • نصب افزونهٔ «خاموش‌کنندهٔ Notice»: این افزونه‌ها فقط علامت را پنهان می‌کنند؛ مثل گرفتن تب‌سنج بدون درمان تب.

خط پایان

خطای Notice در PHP را می‌توان هم دشمن دید و هم راهنما. در پروژه‌هایی که سال‌ها با آن‌ها کار کرده‌ام، سایت‌هایی که لاگ Noticeشان تمیز است، همیشه پایدارتر و سریع‌تر از سایت‌هایی بوده‌اند که این خطاها در آن‌ها نادیده گرفته شده. توصیهٔ من این است: هر ماه یک بار لاگ PHP را باز کنید و Noticeهای تازه را بررسی کنید؛ حتی اگر امروز کاری با آن‌ها ندارید، فقط بدانید که چه چیزی در سایت شما تغییر کرده. اگر روش دیگری برای مدیریت Noticeها دارید یا مورد جالبی در یک پروژه دیده‌اید، در دیدگاه‌ها بنویسید. 🧭