رسیدگی به خطاها در PHP
رسیدگی یا مدیریت خطاها در php
رسیدگی به خطاها در php بسیار ساده است. به صورت پیشفرض اگر خطایی رخ دهد، یک پیغام خطا که توضیح دهنده ی خطا است، همراه با نام فایل و شماره خط به مرورگر فرستاده می شود.
هنگام ایجاد برنامه های تحت وب، بررسی خطاها یک بخش مهم است. اگر کد شما امکان بررسی خطا را نداشته باشد، در این صورت بسیار غیرحرفه ای عمل کرده اید و ممکن است در معرض خطر امنیتی قرار بگیرید.
در زیر بعضی روش های معمول بررسی خطا در php توضیح داده خواهد شد:
- استفاده از دستور ساده ()die
- خطاهای معمولی و راه اندازی رسیدگی کننده خطا
- واقعه نگاری خطاها
استفاده از تابع ()die
این تابع متنی را که به عنوان پارامتر برای آن مشخص کرده ایم، چاپ می کند و از کد جاری خارج می شود.
مثال: در این مثال با استفاده از تابع ()fopen یک فایل متنی را به صورت فقط خواندنی باز می کنیم:
<?php
$file=fopen("welcome.txt","r");
?>
اگر فایل وجود نداشته باشد، با خطای زیر مواجه می شویم:
Warning: fopen(welcome.txt) [function.fopen]: failed to open stream:
No such file or directory in C:\webfolder\test.php on line 2
برای اینکه کاربر با پیغام خطای بالا مواجه نشود، قبل از هر چیز، وجود فایل "welcome.txt" را بررسی می کنیم:
<?php
if(!file_exists("welcome.txt"))
die("File not found");
else
$file=fopen("welcome.txt","r");
?>
کد بالا کارامدتر از کد قبلی است، حالا اگر فایل وجود نداشته باشد بعد از اجرای اسکریپت، پیغام خطای زیر نمایش داده می شود:
File not found
توجه: در اسکریپت بالا، بعد از اجرای دستور ()die، ادامه اجرای اسکریپت متوقف می شود.
متوقف کردن اسکریپت، به این سادگی، همیشه راه درست نیست. بیایید نگاهی به توابع تناوبی رفع خطا در php بیندازیم.
ایجاد یک تابع رسیدگی کننده خطا (error handler)
ایجاد این تابع کاملاً ساده است، و هرگاه که در کد PHP خطایی رخ داد این تابع فراخوانی می شود.
این تابع باید بتواند حداقل با دو پارامتر کار کند(سطح خطا و پیغام خطا) اما تا پنج پارامتر را بپذیرد(اختیاری: فایل، شماره خط و متن پیغام):
نحوه استفاده:
error_function(error_level,error_message,error_file,error_line,error_context)
پارامتر | توضیحات |
---|---|
error_level |
الزامی است، سطح گزارش خطا را مشخص می کند. جدول زیر را برای انواع سطوح گزارش خطا ببینید. |
error_message |
الزامی است، پیغام خطا را برای خطای تعریف شده توسط کاربر مشخص می کند. |
error_file |
اختیاری است. نام فایلی را که خطا در ان رخ داده است مشخص می کند. |
error_line |
اختیاری است. شماره خطی را که خطا در آن رخ داده است مشخص می کند. |
error_context |
اختیاری است. یک آرایه که شامل تمام متغییرهای در حال استفاده هنگام رخداد خطا با مقادیرشان است را مشخص می کند. |
سطوح گزارش خطا:
مقدار | نام ثابت | توضیحات |
---|---|---|
2 | E_WARNING |
خطاهای زمان اجرا غیر جدی. اجرای script متوقف نمی شود |
8 | E_NOTICE |
اخطارهای زمان اجرا.script چیزی پیدا کرده که ممکن است خطا باشد? اما می تواند در اجرای معمولی script نیز رخ دهد |
256 | E_USER_ERROR |
خطای جدی کاربرساز. مانند یک E-ERROR که توسط کابر با استفاده از تابع trigger_error( ) در php به وجود می آید. |
512 | E_USER_WARNING |
هشدار غیرجدی کاربرساز. مانند یک E_WARNING است که توسط کابر با استفاده از تابع trigger_error( ) در php به وجود می آید. |
1024 | E_USER_NOTICE |
اخطار کاربرساز. مانند یک E_NOTICE است که توسط کابر با استفاده از تابع trigger_error( ) در php به وجود می آید. |
4096 | E_RECOVERABLE_ERROR |
خطای جدی گرفتنی. مانند یک E_ERROR است اما بوسیله ی رفع خطای تعریف شده توسط کاربر می توان ان را گرفت(set_error_handler( ) را نیز ببینید) |
8191 | E_ALL |
همه ی خطاها و هشدارها?به جز سطح E_STRICT) E_STRICT در php 6.0 جزئی از E_ALL خواهد شد.) |
حالا اجازه دهید تا یک تابع برای رسیدگی کردن به خطاها ایجاد کنیم، که شامل ورودی های زیر است:
- errno$: سطح خطا
- errstr$: متن خطا
function customError($errno, $errstr)
{
echo "<b>Error:</b> [$errno] $errstr<br />";
echo "Ending Script";
die();
}
کد بالا موقعی که راه اندازی شد، "سطح خطا" و "متن خطا" را می گیرد و سپس با چاپ کردن دو مورد ذکر شده به اجرای اسکریپت پایان می دهد.
در حال حاضر باید تصمیم بگیریم که چه موقع تابع بالا، راه اندازی شود.
تنظیم رسیدگی کننده خطا
ما قصد داریم تابع "customError" را به عنوان پیشفرض رسیدگی کننده خطا در PHP معرفی کنیم، این کار به سادگی با استفاده از تابع زیر در PHP امکان پذیر است:
set_error_handler("customError");
نکته: یک پارامتر دوم می تواند برای مشخص کردن سطح خطا به تابع ()set_error_handler اضافه شود، ولی چون می خواهیم که تابع معمولی مان همه ی خطاها را رفع کند، ()set_error_handler تنها با یک پارامتر فراخوانی می شود.
مثال: در زیر سعی کرده ایم با چاپ متغییر "test$" که وجود ندارد تابع "رسیدگی کننده خطا" یا همان "customError" را تست کنیم:
<?php
function customError($errno, $errstr)
{
echo "<b>Error:</b> [$errno] $errstr";
}
set_error_handler("customError");
echo($test);
?>
خروجی کد بالا:
Error: [8] Undefined variable: test
راه اندازی یک خطا
در اسکریپتی که کاربران می توانند داده وارد کنند، می توان موقع رخداد یک ورودی غیرمجاز خطاها را راه اندازی کرد. در php، این کار با تابع ()trigger_error انجام می شود.
مثال: در این مثال اگر متغییر "test" بزرگتر از "1" باشد، یک خطا رخ می دهد:
<?php
$test=2;
if ($test>1)
{
trigger_error("Value must be 1 or below");
}
?>
خروجی کد بالا:
Notice: Value must be 1 or below
in C:\webfolder\test.php on line 5
یک خطا می تواند هر جایی در اسکریپت که بخواهید راه اندازی شود و با افزودن پارامتر دوم شما می توانید مشخص کنید که چه سطح خطایی راه اندازی شود.
مثال: در این مثال یک خطا با سطح E_USER_WARNING رخ می دهد، اگر متغییر "test" بزرگتر از "1" باشد، تابع رسیدگی کننده خطا، راه اندازی شده و اسکریپت را خاتمه می دهیم:
<?php
function customError($errno, $errstr)
{
echo "<b>Error:</b> [$errno] $errstr<br />";
echo "Ending Script";
die();
}
set_error_handler("customError",E_USER_WARNING);
$test=2;
if ($test>1)
{
trigger_error("Value must be 1 or below",E_USER_WARNING);
}
?>
خروجی کد بالا:
Error: [512] Value must be 1 or below
Ending Script
اکنون که طریقه ی رسیدگی به خطاها و چگونگی راه اندازی آن ها را یاد گرفتیم، اجاز دهید نگاهی به واقعه نگاری (Log) خطاها بیندازیم.
واقعه نگاری خطاها (Log)
به طور پیش فرض، php یک گزارش خطا به سیستم واقعه نگاری سرورها یا یک فایل، بسته به اینکه پیکر بندی گزارش خطا چگونه درفایل php.ini تنظیم شده است ارسال می کند. با استفاده از تابع ()error_log شما می توانید گزارش های خطا را به به یک فایل مشخص شده یا یک مقصد دور ارسال کنید.
ارسال پیغام های خطاها به خودتان از طریق email می تواند روش خوبی برای آگاه شدن از خطاهای خاص باشد.
مثال: در این مثال اگر یک خطای خاص رخ دهد ما یک e-mail را همراه با یک پیغام خطا به آدرس مشخص شده می فرستیم و اسکریپت خاتمه خواهد یافت:
<?php
function customError($errno, $errstr)
{
echo "<b>Error:</b> [$errno] $errstr<br />";
echo "Webmaster has been notified";
error_log("Error:[$errno]$errstr",1,"این آدرس ایمیل توسط spambots حفاظت می شود. برای دیدن شما نیاز به جاوا اسکریپت دارید","From:این آدرس ایمیل توسط spambots حفاظت می شود. برای دیدن شما نیاز به جاوا اسکریپت دارید");
}
set_error_handler("customError",E_USER_WARNING);
$test=2;
if ($test>1)
{
trigger_error("Value must be 1 or below",E_USER_WARNING);
}
?>
خروجی کد بالا:
Error: [512] Value must be 1 or below
Webmaster has been notified
و در ادامه ایمیل دریافت شده چیزی شبیه زیر خواهد بود:
Error: [512] Value must be 1 or below
توجه: این نباید برای همه ی خطاها استفاده شود، خطاهای معین باید با سیستم واقعه نگاری پیش فرض php در سرور ثبت شوند.
برای مشاهده فیلم ها و آموزش های پروژه محور برنامه نویسی PHP کلیک کنید.
- نوشته شده توسط امیر پهلوان صادق
- بازدید: 18493
دیدگاهها
سلام و خداقوت.درقسمت تنظیم رسیدگی کننده خطا, متغیر $errstr از کجا مقدار میگیره؟ خروجی Undefined variable: test از کجا اومده؟
سلام اگر یکبار دیگر با دقت به کد مورد نظر دقت کنید، متوجه خواهید شد که ما در حال چاپ متغیری هستیم که تعریف نشده است، بنابراین بصورت اتوماتیک توسط PHP سطح خطا و متن زیر ایجاد خواهد شد:
errno$: (سطح خطا) --> 8
errstr$: (متن خطا) --> Undefined variable: test
اسکریبت مورد نظر:
<?php
function customError($er rno, $errstr)
{
echo "Error: [$errno] $errstr";
}
set_error_handler("customError");
echo($test);
?>بنابراین زمانی که تابع customError صدا زده می شود، پارامترهای مذکور بصورت اتوماتیک توسط PHP مقداردهی شده اند.
نهایتا وظیفه تابع customError در زیر کاملا واضح است که باعث چاپ همزمان "سطح خطا" و "متن خطا" شده و در انتهای آن با استفاده از تابع die از برنامه خارج می شویم.
function customError($er rno, $errstr)
{
echo "Error: [$errno] $errstr";
echo "Ending Script";
die();
}
اها درسته ممنون.اما مگه اول اموزش نگفتین باید خودمون به خطا رسیدگی کنیم وگرنه php خودش اون دوخط ارور رو چاپ میکنه که از نظر ایمنی مناسب نیست؟یعنی متن خطارو باید خودمون تنظیم کنیم که چی باشه نه بصورن پیش فرض php.مگه هدف از این اموزش همین نبود؟
لطفا به پیام خطایی که بصورت پیشفرض توسط PHP گزارش می شود یکبار دیگر در زیر دقت کنید:
Warning: fopen(welcome.t xt) [function.fopen ]: failed to open stream:
No such file or directory in C:\webfolder\te st.php on line 2
همان طور که در بالا می بینید، داخل پیام خطا، "نام فایل" و "آدرس فایلی" که خطا در آن اتفاق افتاده است بصورت کامل ذکر شده که از لحاظ امنیتی، نباید نمایش داده شود. اما ما با استفاده از تابع customError می توانیم موارد ذکر شده را از داخل متن خطا حذف کنیم و کلا مدیریت گزارش خطاها را بدست بگیریم.
سلام خسته نباشید
بعد از اجرای کد چنین خطایی دارم ممکنه کمک کنید:Parse error: syntax error, unexpected T_ELSE in C:\xampp\htdocs \f\r.php on line 6529
با سلام و تشکر.
متن کد نیومده! ولی متن خطا داره میگه، تو کدها خطای گرامری وجود داره.
یه جایی تو دستور if else احتمالا مرتکب خطا شدید.
این موارد رو چک کنید.
با عرض سلام وخسته مباشید و تشکر بابت سایت خوبتون
میخاستم اگه بشه این کد رو که در بالا نوشته بودید توضیح بدید .ممنون.
با سلام.
دقیقا منظور شما کدوم قسمت از کد هست؟؟؟
من دستور if رو خوب بلدم. شما اصلا سوال بنده رو متوجه نشدید.
من میگم دستور if دو حالت داره. یا شرطش درسته یا غلط.
اینجا اگر شرط درست باشه (فایل وجود نداشته باشه) ، ()die اجرا میشه و بعد از اون هیچ چیزی اجرا نمیشه. (یعنی else اجرا نمیشه)
و اگر شرط غلط باشه (فایل وجود داشه باشه) ، از بلاک if خارج میشه و دستور بعد از if هرچی باشه اجرا میشه و حالت دیگری وجود نداره که else نیاز داشته باشه.
با سلام
معمول ترین نوع ساختار تصمیم گیری if است. یک دستور if می گوید "اگر شرطی برقرار است کد معینی را انجام بده". دستور if-else به دو شکل می تواند باشد: همراه با else يا بدون آن.
if(expression)
{
statement
}
يا
if(expression)
{
statement
}
else
{
statement
}
بدنبال کلمه if یک پرانتز می آید که عبارت شرط در آن قرار دارد و يک مقدار بولين false يا true توليد می کند (در C به صورت صفر و غير صفر ارزيابی می شود). با درست و غلط بودن عبارت شرطی مسير اجرا تعيين می شود. اگر درست باشد دستور بعد از if اجرا می شود. اگر else وجود داشته باشد در صورت برقرار نبودن شرط دستور بعد از else اجرا می شود.
با توجه به توضیحات ذکر شده، در صورت برقرار نبودن شرط if عبارت جلوی else اجرا می شود. بر اساس سوال شما، یعنی در صورتی که فایل وجود داشته باشد و نخواهیم در صورت وجود فایل کار دیگری انجام دهیم بله می توانیم else را بر داریم.
به نقل از شهربانو دوستی:
نه من نگفتم عبارت جلوی else برداشته بشه. حرف من اینه که خود کلمه ی else از این کد برداشته بشه. یعنی فقط خط سوم رو حذف کنیم. اگر این کار رو بکنیم نتیجه هیچ تغییری نمی کنه. امتحان کنید.
دقیقا صحبت من هم همین بود. اگر فقط عبارت جلوی else برداشته شود که دستور صحیح نیست. طبق گفته قبل در صورتی که نیازی ندارید در صورت بر قرار نبودن شرط if کار دیگری انجام شود می توانید else به همراه عبارت جلوی آن را بردارید.
به نقل از شهربانو دوستی:
من از اول دارم میگم کاری به عبارت جلوی else نداشته باشید. فقط else را بردارید شما دوباره میگید else به همراه عبارت جلوی else.
حرف من این است که اگر نیاز به انجام کاری هم باشد (مثل الآن) ، می توان کلمه ی else را برداشت و عبارت جلوی else بدون else نوشت.
با سلام
در تکمیل صحبت های خانم دوستی و همچنین نظرات آقای ربانی:
اینکه آقای ربانی می فرماید که با برداشتن کلمه ی else عبارت شرطی بدون هیچ مشکلی اجرا می شود درسته مثلا می تونید عبارت زیر را امتحان کنید:
< ?php
if (1>2)
echo "1>2";
echo "2>1";
? >
در کدهای بالا در خط کد 7 دستور else را برداشته ایم و عبارت شرطی به درستی عمل می کند.
در زبان پایتون اگر اشتباه نکنم عبارات شرطی به این شکل نوشته می شوند(در یکی از حالت هایش) . به نظرم این طور نوشتن دستورات در php مربوط به نسخه های قدیمی آن باشد. و در php نوین، ذکر شده است که عبارت else را اضافه کنیم.
در سومین کد قسمت استفاده از تابع ()die ، یعنی کد زیر:if(!file_exists("welcome.txt"))
die("File not found");
else
$file=fopen("we lcome.txt","r") ;
مگر بعد از اجراي دستور ()die، ادامه اجراي اسکريبت متوقف نمی شود؟
پس دیگر نوشتن کلمه ی else نیازی نیست! اگر بلوک if اجرا شد ادامه ی اسکریپت اجرا نمی شود و اگر اجرا نشد بقیه اجرا می شود.
پس کاربرد کلمه ی else در اینجا چیست؟
مهدی جان فکر می کنم شما باید اول دستور if رو خوب یاد بگیری.
درسته که در این مثال ما عمداً کاری کردیم که خطا ایجاد شود، یعنی فایل welcome.txt را درست آدرس دهی نکردیم...!
اما توجه داشته باشید که زمانی که آدرس دهی بدرستی انجام شده باشد، باید به قسمت else منتقل شویم و فایل مورد نظرمان را open کنیم.
منظور من اینه که کلمه ی else رو از کد بالا حذف کنیم هم هیچ اتقاقی نمی افته. یعنی خط 3 حذف بشه باز هم کد به درستی کار می کنه.