در بخش قبلي در مورد استسنا بحث گرديد، اما بخاطر اهميت موضوع دراين بخش تحت عنوان مديريت استسنا، مطالب جامعتر وكاربردي تري بيان ميگردد .ممكن است بعضي از مطالب تكراري باشد،اما بخاطر پيوستگي مطلب ، تكرار در بيان توضيحات كمك ميكند.
استسناها براي تغيير جريان عادي اجراي اسكريپت، هنگاميكه خطائي پيش مي آيد، بكار ميروند.
درPHP5 براي مقابله با خطا ها روش جديد شئ گرائي پيش بيني گرديد .در صورت بروز يك خطاي مشخص (استسنائي) با مديريت آن، جريان عادي اجرا تغيير كند ، بآن عامل تغيير استسنا گويند. روش شي گرائي درجهت مديريت اين پروسه بكار گرفته ميشود .با بكارگيري اين روش اطلاعات موارد استسنا بصورت قابل درك ميتواند مشاهده شود.
هنگاميكه بيك استسنا برخورد نموديد، بطور معمول موارد زير اتفاق مي افتد.
1ـ وضعيت كد جاري ذخيره ميشود.
2ـ اجراي اسكريپت بيك تابع از پيش تعريف شده منتقل ميشود .اين تابع مديريت استسنا ميباشد
3،ـ با توجه به وضعيت پيش آمده ممكن است اجراي برنامه ازهمان نقطه ذخيره شده اجراگردد يا اجرا متوقف شده ويا ازيك محل ديگري اجرا، ادامه يابد.
در اين بخش روشهاي مختلف مديريت خطا كه مطابق زيرند، بيان ميگردند
1ـ استفاده از استسناهاي پايه
2ـ ايجاد كنترل كننده سفارشي استسنا
3ـ چند استسنائي
4ـ پرتاب مجدد استسنا
5ـ تنظيم كننده استسنا سطح بالا
نكته ـ استسناها بايد با شرايط خطا مورد استفاده قرار گيرند و براي پرش معمولي آنرا بكار نبريد.
بدنبال هر كدام از روشهاي فوق را براي كنترل ومديريت خطا باذكر مثال متناسب شرح داده ميشود.
هنگاميكه استسنائي رخ ميدهد وپرتاب ميشود، كد زير آن اجرا نميشود وphp كوشش ميكندبلوك catchمتناسب آنرا پيدا نمايد . اگر آن بلوك معرفي نشده باشد، اقدام پيش فرض خود را انجام ميدهد.
در صورتيكه يك استسنا شنا سائي نشود، پيغام سختي در ارتباط باآن صادر ميشود .براي درك بهتر مطلب ، در مثال زير استسنائي اتفاق مي افتد، اما شناسائي نميشود.
مثال ـ برخورد با استسنا بدون شناسائي
<?php //create function with an exception function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; } //trigger exception checkNum(1); checkNum(4); ?>
حاصل اجراي آن اعلام خطاي زير وتوقف برنامه بعداز اعلام خطا، اقدام پيش فرض در عدم شناسائي
Fatal error: Uncaught exception 'Exception' with message 'Value must be 1 or below' in E:\xampp\htdocs\xampp\vbtest\temp.php:5 Stack trace: #0 E:\xampp\htdocs\xampp\vbtest\temp.php(12): checkNum(4) #1 {main} trown in E:\xampp\htdocs\xampp\vbtest\temp.php on line 5
مثال بالا فقط شال دستورthrow بود، يعني شنا سائي وپرتاب بدون گرفتن آن . اما كنترل اين روند بايد ادامه يابد ورها نشود .براي تكميل روند بايد دستورات catchوtry متناسب با throwدرگير شوند، تا مشكل برطرف وتسلط كاربر بيشترگردد.
بدين ترتيب كد مناسب استسنا شامل موارد يا بلوكهاي زيراست.
- try -1بلوك فوق منبع استسناست .واين منبع تحت كنترل عوامل نظا رتي روال قرارميگيرد .تابع يا اسكريپتي كه از استسنا ي بلوك استفاده مي نمايد، بايد در بلوك فوق باشد .اگر استسنا فعال نشود، بلوك مسير عادي اجرا را ادامه ميدهد .اگراستسنا فعال شود ازطريقtrow پرتاب متناسبي شكل ميگيرد.
- throw -2بااين دستور يك پرتاب ايجاد ميشود .هر پرتابي بايد حداقل يك گيرنده داشته باشد .گيرنده پرتاب بلوكcatch است كه با مشخصات پرتاب گر منطبق باشد.
-catch -3يك استسنا را دريافت وبازيابي ميكند، وشئ حاوي اطلاعات آن ايجاد مي ميشود، تا بتوان با استفاده ازآن بكاربر كمك رساند
در مثال زير براي كنترل مناسب استسنا از تركيب سه بلوك فوق استفاده شده استمثال -.
<?php //create function with an exception function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; } //trigger exception in a "try" block try { checkNum(2); //If the exception is thrown, this text will not be shown echo 'If you see this, the number is 1 or below'; } //catch exception catch(Exception $e) { echo 'Message: ' .$e->getMessage(); } ?>
اجراي برنامه فوق با خطاي زير مواجه ميشود.
توضيحات برنامه مطابق زير است.
1ـ تابعchecknum( ) كنترل ميكند كه عدد دريافتي بزرگتر از يك است يا خير. اگر بزرگتر از يك باشد، يك استسنا ايجاد ميكند.
2ـ فراخوانيchecknum( ) در بلوك"try" انجام ميشود.
3ـ پرتاب استسنا در تابعchecknum() انجام ميشود.
4ـ بلوكcatch استسنارا دريافت وبازيابي اطلاعات نموده وشئ$e را ايجاد واطلاعات مورد نيازاز استسنا را در آن قرار ميدهد.
5ـ با فراخواني تابع$e->getMessage() خطاي استسنا بازتاب داده ميشود
نكته ـ اگر دستوري بعد از بلوكcatch قرار گيرد دراين روش در هر شرايطي با استسنا يا بدو ن
استسنا اجرا ميگردد .خودتان يك دستور
جهت ايجاد يك كنترل كننده خاص براي استسنا ها، بايد آن داراي تابعي باشد كه در صورت بروز استسنا آن را فراخواند .كلاس بايد داراي پسوندException باشد .
اين كلاس خصوصيات كلاسException از php را بارث ميبرد، وتوابع اضافه شده ميتوانند ارآنها استفاده نمايند .تعريف كلاس مطابق زير است.
class customException extends Exception { public function errorMessage() { //error message $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile() .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address'; return $errorMsg; } }
در كلاس پايهExecption ازphp كه در تعريف كلاس سفارشي فوق استفاده شده ، متدهاي getLine() , getFile(), getMessage( )كه در بخش قبلي هم بيان گرديد، وجود دارد كه كلاس جديد هم آنها را به ارث مي برد .اين توابع اطلاعات استسناي رخ داده را دارند، كه دراين كلاس سفارشي براي تنظيم خطا استفاده شده اند.
مثال ـ در مثال زير يك كلاس سفارشي براي مديريت استسنا ايجاد شده وازآن استفاده ميگردد.
<?php class customException extends Exception { public function errorMessage() { //error message $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile() .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address'; return $errorMsg; } } $email = "someone@example...com"; try { //check if if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //throw exception if email is not valid throw new customException($email); } } catch (customException $e) { //display custom message echo $e->errorMessage(); } ?>
تشريح مثال: برنامه فوق استسنائي ايجاد ميكندو كلاس سفارشي فوق ميگيرد ومشخصات آنرا تنظيم مينمايد.مطابق زير:
1ـ كلاس سفارشي customException() مطابق كلاسphp Exception ايجاد متدها وخصوصيات آنرا به ارث ميبرد.
2ـ تابعerrMessage()ايجاد ميشود، واگرآدرس ايميلي داراي خطا باشد اين تابع پيغام مناسب را برگشت ميدهد.
3ـ در متغير$email يك آدرس ايميل نادرست قرار ميگيرد.
4ـ بلوكtry اجرا ميشود و آدرس نامعتبر ايميل را تشخيص داده ويك استسنا از طريقthrow ايجاد ميكند .در ايجاد اين اتفاق تابعcustomException() خطاي حاصله را تنظيم مينما.يد
5ـ بلوكcatch استسنارا دريافت كرده وخطاي تنظيمي را نمايش ميدهد.
6ـ اجراي بلوكtry متوقف وبرنامه از انتهاي بلوكcatch ادامه ميبابد .البته دستوري در انتها وجود ندارد كه اجراشود .ولي جهت آزمايش دستوري اضافه كنيد ونتيجه را مشاهده كنيد.
اين امكان وجود دارد كه يك اسكريپت از چندين استسنا براي بررسي شرايط مختلف استفاده نمايد.
دراستفاده از بلوكهاي متعدد
مثال ـ در مثال زير براي دو استسنا از دو كلاس استفاده شده است.
<?php class customException extends Exception { public function errorMessage() { //error message $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile() .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address'; return $errorMsg; } } $email = "someone@example.com"; try { //check if if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //throw exception if email is not valid throw new customException($email); } //check for "example" in mail address if(strpos($email, "example") !== FALSE) { throw new Exception("$email is an example e-mail"); } } catch (customException $e) { echo $e->errorMessage(); } catch(Exception $e) { echo $e->getMessage(); } ?>
اسكريپت فوق در يك بلوكtry دو شرط را بررسي ميكند، و در صورت عدم رعايت هركدام از آنها يك استسنا ايجاد ميشو بشرح زير:
1ـ كلاسcustomException براساس كلاس قديميException ايجاد ميشودو تمام ويژگي و متدهاي آنرا به ارث ميبرد.
2ـ تابع errorMessage() در همان كلاس ايجاد ميشود .كار تابع فوق تنظيم پيغام خطا و برگرداندن آن .اين خطا در ارتباط با استسناي ايميل ميباشد.
3ـ درمتغير$email آدرس ايميل قابل قبول قرار ميگيرد .محتوي اين آدرس كلمه
"example"قرار دارد . 4ـ ناحيهtry اجرا ميشود ودر بررسي اول استسنائي رخ نميدهد.
5ـ دومين شرط بلوكtry كه بررسي وجود كلمه"example" بوده منجر بايجاد استسنا ميشود
6ـ بلوك catch(Exception $e) مربوط باستسناي فوق بوده كه پيغام وجود "example"را ميدهد .
در صورتي اين استسنا ايجاد ميشود، كه استسنايcustomException رخ ندهد .اما اگر اين رخ ميداد اجراي بلوكtry پس از اعلام پيغام متوقف ميگرديد، واستسناي بعدي بررسي نميشد .
در برخي از موارد ممكن است بخواهيد، يك استسناي رخداده را با روش متفاوت استانداردش مديريت نمائيد .اين امكان وجودارد كه بتوان حالت استاندارد را ناديده گرفته وآن را دوباره پرتاب نمود
يك سكريپت بايد خطاي سيستم را از كاربران پنهان نمايد .خطاي سيستم ممكن براي كد نويس مهم باشد اما براي كاربر جالب نيست .براي آسانتر كردن كاربر، ميتوان پيغام مناسبتر داد .اين كار ميتواند با پرتاب مجدد، انجام گيرد.
مثال ـ در مثال زير يك استسنا دوبار پرتاب شده است.
<?php class customException extends Exception { public function errorMessage() { //error message $errorMsg = $this->getMessage().' is not a valid E-Mail address.'; return $errorMsg; } } $email = "someone@example.com"; try { try { //check for "example" in mail address if(strpos($email, "example") !== FALSE) { //throw exception if email is not valid throw new Exception($email); } } catch(Exception $e) { //re-throw exception throw new customException($email); } } catch (customException $e) { //display custom message echo $e->errorMessage(); } ?>
شرح مثال مطابق زير:
1ـ مشابه مثال قبليcustomException() ايجاد ميشود.
2ـ تابعerrorMessage() ايجاد ميشود .اين تابع پيغام خطا را تنظيم وبرميگرداند.
3ـ مشابه مثال قبلي متغير$email آدر س ايميل را در يافت ميكند.
4ـ بلوكtry شامل بلوكtry داخلي ديگريست براي پرتاب مجدد
5ـ چون ايميل داراي كلمه"example" است استسنا رخ ميدهد.
6ـ در بلوكcatch استسنا گرفته ميشود اما درآن استسناي بلوك"customException" رخ ميدهد.
7ـ بلوكcustomException استسنا دوباره راگرفته وپيغام مربوطه رانمايش ميدهد.
اگرcatch استسنا در بلوك بررسي خود قرار نداشته باشد، دنبال catch در سطوح بالاتراست .
باتابعset_exception_handler( ) ميتوان يك تابع كنترل استسنا نا شناخته بر قرار نمود .يعني اگر با دستورthrow استسناي بدونcatch باشد ،آن تابع آنرا در يافت مينمايد . اين استسنا فقط داراي پيغام بدون اطلاعات مكان وقوع ميباشد.
<?php function myException($exception) { echo "<b>Exception:</b> " . $exception->getMessage(); } set_exception_handler('myException'); throw new Exception('Uncaught Exception occurred'); ?>
خروجي اسكريپت فوق بايد مطابق زير باشد.
برنامه فوق فاقد بلوكcatch ميباشد، در عوض داراي تابع گيرنده ميباشد كه استسناي نا شناخته دريافت ميكند .تابع گيرنده با تابعset_exception_handler() معرفي ميشود .
1ـ كد ممكن است در يك بلوكtry محدود باشد ، كه ميتواند در پيدا كردن استسنا كمك نمايد.
2ـ هر بلوك پرتاب كننده بايد حداقل يك بلوك گيرنده يعنيcatch داشته باشد.
3ـ چند بلوكcatch ميتواند براي گرفتن كلاسهاي مختلف استسنا بكار رود.
4ـ استسنا ها ميتواند در بلوكcatch كه داخل بلوكtry هستند، پرتاپ يا دو باره پرتاب شوند.
قانون ساده: اگر چيزي را پرتاب ميكنيد(throw) بايد آنرا بگيريد.