‎‎مديريت استسناPHP Exception Handling -‎

Previous >    <Next  

‎در بخش قبلي در مورد استسنا بحث گرديد، اما بخاطر اهميت موضوع دراين بخش تحت عنوان مديريت ‎استسنا، مطالب جامعتر وكاربردي تري بيان ميگردد .ممكن است بعضي از مطالب تكراري باشد،اما ‎بخاطر پيوستگي مطلب ، تكرار در بيان توضيحات كمك ميكند.

‎‎استسناها براي تغيير جريان عادي اجراي اسكريپت، هنگاميكه خطائي پيش مي آيد، بكار ميروند.

‎‎استسنا چيستWhat is an Exception -‎

‎درPHP5 براي مقابله با خطا ها روش جديد شئ گرائي پيش بيني گرديد .در صورت بروز يك خطاي ‎مشخص (استسنائي) با مديريت آن، جريان عادي اجرا تغيير كند ، بآن عامل تغيير استسنا گويند. ‎روش شي گرائي درجهت مديريت اين پروسه بكار گرفته ميشود .با بكارگيري اين روش اطلاعات موارد ‎استسنا بصورت قابل درك ميتواند مشاهده شود.

‎‎هنگاميكه بيك استسنا برخورد نموديد، بطور معمول موارد زير اتفاق مي افتد.

‎‎ 1‎ـ وضعيت كد جاري ذخيره ميشود.

‎‎ 2‎ـ اجراي اسكريپت بيك تابع از پيش تعريف شده منتقل ميشود .اين تابع مديريت استسنا ميباشد

‎ 3‎،ـ با توجه به وضعيت پيش آمده ممكن است اجراي برنامه ازهمان نقطه ذخيره شده اجراگردد ‎يا اجرا متوقف شده ويا ازيك محل ديگري اجرا، ادامه يابد.

‎‎در اين بخش روشهاي مختلف مديريت خطا كه مطابق زيرند، بيان ميگردند

‎‎ 1‎ـ استفاده از استسناهاي پايه

‎‎ 2‎ـ ايجاد كنترل كننده سفارشي استسنا

‎‎ 3‎ـ چند استسنائي

‎‎ 4‎ـ پرتاب مجدد استسنا

‎‎ 5‎ـ تنظيم كننده استسنا سطح بالا

‎نكته ـ استسناها بايد با شرايط خطا مورد استفاده قرار گيرند و براي پرش معمولي آنرا بكار ‎نبريد.

‎‎بدنبال هر كدام از روشهاي فوق را براي كنترل ومديريت خطا باذكر مثال متناسب شرح داده ميشود.

‎‎استفاده از استسناهاي پايهBasic Use of Exceptions -‎

‎هنگاميكه استسنائي رخ ميدهد وپرتاب ميشود، كد زير آن اجرا نميشود و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);

?> 

--(go to editor for change code and run)

‎‎حاصل اجراي آن اعلام خطاي زير وتوقف برنامه بعداز اعلام خطا، اقدام پيش فرض در عدم شناسائي

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

‎‎دستوارتTry, throw and catch -‎

‎مثال بالا فقط شال دستور‎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();
}
?> 

--(go to editor for change code and run)

‎‎اجراي برنامه فوق با خطاي زير مواجه ميشود.

‎Message: Value mst be 1 or below‎

‎‎توضيحات برنامه مطابق زير است.

‎ 1‎ـ تابع‎checknum( )‎ كنترل ميكند كه عدد دريافتي بزرگتر از يك است يا خير. ‎اگر بزرگتر از يك باشد، يك استسنا ايجاد ميكند.

‎‎ 2‎ـ فراخواني‎checknum( ) ‎ در بلوك‎"try‎"‎ انجام ميشود.

‎‎ 3‎ـ پرتاب استسنا در تابع‎checknum()‎‎ انجام ميشود.

‎ 4‎ـ بلوكcatch استسنارا دريافت وبازيابي اطلاعات نموده وشئ‎$e‎ را ايجاد ‎واطلاعات مورد نيازاز استسنا را در آن قرار ميدهد.

‎‎ 5‎ـ با فراخواني تابع‎$e-‎>getMessage()‎ ‎ خطاي استسنا بازتاب داده ميشود

‎نكته ـ اگر دستوري بعد از بلوكcatch قرار گيرد دراين روش در هر شرايطي با استسنا يا بدو ن ‎استسنا اجرا ميگردد .خودتان يك دستور‎ echo ‎"last message‎"; ‎ ‎را در انتها قرار دهيد ونتيجه را ‎مشاهده كنيد .انچه كه درمورد توقف بعد از استسنا گفته شد، در ناحيهtry صادق است .

‎‎ايجاد كلاس سفارشي استسناCreating a Custom Excption Class -‎

‎جهت ايجاد يك كنترل كننده خاص براي استسنا ها، بايد آن داراي تابعي باشد كه در صورت بروز ‎استسنا آن را فراخواند .كلاس بايد داراي پسوند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();
}
?> 

--(go to editor for change code and run)

‎تشريح مثال: ‎برنامه فوق استسنائي ايجاد ميكندو كلاس سفارشي فوق ميگيرد ومشخصات آنرا تنظيم مينمايد.مطابق ‎زير:

‎ 1‎ـ كلاس سفارشي‎ customException()‎ ‎ مطابق كلاسphp Exception ايجاد ‎متدها وخصوصيات آنرا به ارث ميبرد.

‎ 2‎ـ تابع‎errMessage()‎‎ايجاد ميشود، واگرآدرس ايميلي داراي خطا باشد اين تابع ‎پيغام مناسب را برگشت ميدهد.

‎‎ 3‎ـ در متغير‎$email‎ يك آدرس ايميل نادرست قرار ميگيرد.

‎ 4‎ـ بلوكtry اجرا ميشود و آدرس نامعتبر ايميل را تشخيص داده ويك استسنا از طريقthrow ‎ايجاد ميكند .در ايجاد اين اتفاق تابعcustomException()‎ خطاي حاصله را تنظيم مينما.يد

‎‎ 5‎ـ بلوكcatch استسنارا دريافت كرده وخطاي تنظيمي را نمايش ميدهد.

‎ 6‎ـ اجراي بلوكtry متوقف وبرنامه از انتهاي بلوكcatch ادامه ميبابد .البته دستوري در ‎انتها وجود ندارد كه اجراشود .ولي جهت آزمايش دستوري اضافه كنيد ونتيجه را مشاهده كنيد.

‎‎چنداستسنائيMultiple Exceptions -‎

‎اين امكان وجود دارد كه يك اسكريپت از چندين استسنا براي بررسي شرايط مختلف استفاده نمايد. ‎دراستفاده از بلوكهاي متعدد‎ if else ‎ ممكن است چند استسنا بوجود ‎آيد .آنان ممكن است از كلاسهاي متفاوت جهت دادن پيغام مناسب بكارگرفته شوند.

‎‎مثال ـ در مثال زير براي دو استسنا از دو كلاس استفاده شده است.

<?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();
}
?> 

--(go to editor for change code and run)

‎اسكريپت فوق در يك بلوكtry دو شرط را بررسي ميكند، و در صورت عدم رعايت هركدام از آنها يك ‎استسنا ايجاد ميشو بشرح زير:

‎ 1‎ـ كلاسcustomException براساس كلاس قديميException ايجاد ميشودو تمام ويژگي ‎و متدهاي آنرا به ارث ميبرد.

‎ 2‎ـ تابع‎ errorMessage()‎‎ در همان كلاس ايجاد ميشود .كار تابع فوق تنظيم پيغام ‎خطا و برگرداندن آن .اين خطا در ارتباط با استسناي ايميل ميباشد.

‎‎ 3‎ـ درمتغير‎$email‎ آدرس ايميل قابل قبول قرار ميگيرد .محتوي اين آدرس كلمه

‎"example‎"‎قرار دارد .

‎ 4‎ـ ناحيهtry اجرا ميشود ودر بررسي اول استسنائي رخ نميدهد.

‎‎ 5‎ـ دومين شرط بلوكtry كه بررسي وجود كلمه‎"example‎"‎ بوده منجر بايجاد استسنا ميشود

‎ 6‎ـ بلوك‎ catch(Exception $e) ‎مربوط باستسناي فوق بوده كه پيغام وجود ‎"example‎"‎را ميدهد .

‎در صورتي اين استسنا ايجاد ميشود، كه استسنايcustomException رخ ندهد .اما اگر اين رخ ميداد ‎اجراي بلوكtry پس از اعلام پيغام متوقف ميگرديد، واستسناي بعدي بررسي نميشد .

‎‎پرتاپ مجدد استسناRe-‎throwing Exception -‎

‎در برخي از موارد ممكن است بخواهيد، يك استسناي رخداده را با روش متفاوت استانداردش مديريت ‎نمائيد .اين امكان وجودارد كه بتوان حالت استاندارد را ناديده گرفته وآن را دوباره پرتاب نمود

‎يك سكريپت بايد خطاي سيستم را از كاربران پنهان نمايد .خطاي سيستم ممكن براي كد نويس مهم باشد ‎اما براي كاربر جالب نيست .براي آسانتر كردن كاربر، ميتوان پيغام مناسبتر داد .اين كار ‎ميتواند با پرتاب مجدد، انجام گيرد.

‎‎مثال ـ در مثال زير يك استسنا دوبار پرتاب شده است.

<?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();
}
?> 

--(go to editor for change code and run)

‎‎شرح مثال مطابق زير:

‎‎ 1‎ـ مشابه مثال قبلي‎customException()‎ ‎ ايجاد ميشود.

‎ 2‎ـ تابع‎errorMessage()‎ ‎ ايجاد ميشود .اين تابع پيغام خطا را تنظيم ‎وبرميگرداند.

‎‎ 3‎ـ مشابه مثال قبلي متغير‎$email‎ آدر س ايميل را در يافت ميكند.

‎‎ 4‎ـ بلوكtry شامل بلوكtry داخلي ديگريست براي پرتاب مجدد

‎‎ 5‎ـ چون ايميل داراي كلمه‎"example‎"‎ است استسنا رخ ميدهد.

‎‎ 6‎ـ در بلوكcatch استسنا گرفته ميشود اما درآن استسناي بلوك‎"customException‎"‎ رخ ميدهد.

‎‎ 7‎ـ بلوكcustomException استسنا دوباره راگرفته وپيغام مربوطه رانمايش ميدهد.

‎‎اگرcatch استسنا در بلوك بررسي خود قرار نداشته باشد، دنبال catch در سطوح بالاتراست .

‎‎تنظيم كننده استسنا سطح بالاSet a Top Level Exception Handler -‎

‎باتابع‎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');
?> 

--(go to editor for change code and run)

‎‎خروجي اسكريپت فوق بايد مطابق زير باشد.

‎Exception: Uncaught Exception occurred

‎برنامه فوق فاقد بلوكcatch ميباشد، در عوض داراي تابع گيرنده ميباشد كه استسناي نا شناخته ‎دريافت ميكند .تابع گيرنده با تابع‎set_exception_handler()‎‎ معرفي ميشود .

‎‎قوانين استسناهاRules for exceptions -‎

‎‎ 1‎ـ كد ممكن است در يك بلوكtry محدود باشد ، كه ميتواند در پيدا كردن استسنا كمك نمايد.

‎‎ 2‎ـ هر بلوك پرتاب كننده بايد حداقل يك بلوك گيرنده يعنيcatch داشته باشد.

‎‎ 3‎ـ چند بلوكcatch ميتواند براي گرفتن كلاسهاي مختلف استسنا بكار رود.

‎ 4‎ـ استسنا ها ميتواند در بلوكcatch كه داخل بلوكtry هستند، پرتاپ يا دو باره پرتاب ‎شوند.

‎قانون ساده: ‎اگر چيزي را پرتاب ميكنيد(throw) ‎بايد آنرا بگيريد.


Previous >    <Next