Διαχείριση Εξαιρέσεων PHP

Η εξαίρεση (Exception) χρησιμοποιείται για να αλλάξει τη κανονική ροή του σενάριου όταν συμβαίνει ένα συγκεκριμένο σφάλμα.

Τι είναι η εξαίρεση;

Το PHP 5 παρέχει μια νέα μέθοδο προσανατολισμού αντικειμένων για την αντιμετώπιση σφαλμάτων.

Η αντιμετώπιση εξαιρέσεων χρησιμοποιείται για να αλλάξει τη κανονική ροή του σενάριου όταν συμβαίνει ένα συγκεκριμένο σφάλμα (εξαίρεση). Αυτό το σφάλμα ονομάζεται εξαίρεση.

Όταν προκαλείται εξαίρεση, συνήθως συμβαίνει:

  • Η τρέχουσα κατάσταση του κώδικα αποθηκεύεται
  • Ο κώδικας εκτέλεσης μετακινείται σε μια προκαθορισμένη συνάρτηση επεξεργαστή εξαιρέσεων
  • Ανάλογα με την κατάσταση, ο επεξεργαστής μπορεί να ξεκινήσει εκ νέου τον κώδικα από την αποθηκευμένη κατάσταση του κώδικα, να σταματήσει την εκτέλεση του σενάριου ή να συνεχίσει τον κώδικα από άλλη θέση του κώδικα

Θα παρουσιάσουμε διαφορετικές μεθόδους αντιμετώπισης σφαλμάτων:

  • Βασική χρήση εξαιρέσεων
  • Δημιουργία προσαρμοσμένου επεξεργαστή εξαιρέσεων
  • Πολλαπλές εξαιρετικές καταστάσεις
  • Επανεκθέτηση εξαιρετικής κατάστασης
  • Ρύθμιση ανώτατου επεξεργαστή εξαιρέσεων

Βασική χρήση εξαιρέσεων

Όταν προκαλείται εξαίρεση, ο κώδικας που ακολουθεί δεν θα συνεχιστεί, το PHP θα προσπαθήσει να βρει έναν ταιριάζοντα μπλοκ κώδικα "catch".

Αν η εξαίρεση δεν συλληφθεί και δεν χρησιμοποιηθεί η set_exception_handler() για την αντίστοιχη επεξεργασία, θα προκύψει ένα σοβαρό σφάλμα (καταστροφικό σφάλμα) και θα εμφανιστεί το μήνυμα σφάλματος "Uncaught Exception" (μη συλληφθείσα εξαίρεση).

Ας προσπαθήσουμε να προκαλέσουμε μια εξαίρεση, χωρίς να την συλλαμβάνουμε:

<?php
//create function with an exception
function checkNum($number)
 {
 if($number>1)
  {
  throw new Exception("Η τιμή πρέπει να είναι 1 ή λιγότερη");
  }
 return true;
 }
//trigger exception
checkNum(2);
?>

Ο κώδικας θα προκαλέσει ένα σφάλμα όπως αυτό:

Καταστροφικό σφάλμα: μη προεπιλεγμένη εξαίρεση 'Exception' 
με μήνυμα 'Η τιμή πρέπει να είναι 1 ή κάτω από αυτό' στο C:\webfolder\test.php:6 
Stack trace: #0 C:\webfolder\test.php(12): 
checkNum(28) #1 {main} throw in C:\webfolder\test.php on line 6

Try, throw και catch

Για να αποφύγουμε τα σφάλματα που εμφανίζονται στο παραπάνω παράδειγμα, πρέπει να δημιουργήσουμε κατάλληλο κώδικα για την αντιμετώπιση εξαιρέσεων.

Ο σωστός δίαυλος αντιμετώπισης θα πρέπει να περιλαμβάνει:

  1. Προσπάθησε - Οι λειτουργίες που προκαλούν εξαιρέσεις πρέπει να βρίσκονται μέσα σε ένα μπλοκ κώδικα "try". Αν δεν προκαλείται εξαίρεση, ο κώδικας θα συνεχιστεί κανονικά. Ωστόσο, αν προκαλείται εξαίρεση, θα προκύψει μια εξαίρεση.
  2. Εκτόξευση - Εδώ καθορίζεται πώς θα εκτυπωθεί η εξαίρεση. Κάθε "throw" πρέπει να έχει τουλάχιστον ένα "catch"
  3. Κατάληψη - Ο κώδικας "catch" θα καταγράψει την εξαίρεση και θα δημιουργήσει ένα αντικείμενο που περιέχει πληροφορίες για την εξαίρεση

Ας εκτυπώσουμε μια εξαίρεση:

<?php
//Δημιουργία μιας συναρτήσης που μπορεί να εκτυπώσει εξαίρεση
function checkNum($number)
 {
 if($number>1)
  {
  throw new Exception("Η τιμή πρέπει να είναι 1 ή λιγότερη");
  }
 return true;
 }
//Εκτόξευση εξαιρέσεων μέσα στο κώδικα "try"
try
 {
 checkNum(2);
 //Αν εκτυπωθεί η εξαίρεση, αυτό το κείμενο δεν θα εμφανιστεί
 echo 'Αν δείτε αυτό, ο αριθμός είναι 1 ή λιγότερος';
 }
//Κατάληψη εξαιρέσεων
catch(Exception $e)
 {
 echo 'Μήνυμα: ' .$e->getMessage();
 }
?>

Ο κώδικας θα αποδώσει ένα σφάλμα όπως αυτό:

Μήνυμα: Η τιμή πρέπει να είναι 1 ή λιγότερη

Example explanation:

Ο κώδικας εκτυπώνει μια εξαίρεση και την κ捕获

  1. Δημιουργία της συναρτήσης checkNum(). Ελέγχει αν ο αριθμός είναι μεγαλύτερος από 1. Αν ναι, τότε εκτυπώνει μια εξαίρεση.
  2. Η συναρτήση checkNum() καλείται μέσα στο κώδικα "try".
  3. Η εξαίρεση στον ορισμό της συναρτήσης checkNum() εκτυπώνεται
  4. Ο κώδικας "catch" λαμβάνει την εξαίρεση και δημιουργεί ένα αντικείμενο που περιέχει πληροφορίες για την εξαίρεση ($e).
  5. Με την κλήση του $e->getMessage() από το αντικείμενο exception, εκτυπώνεται το μήνυμα σφάλματος της εξαιρέσης

Ωστόσο, για να ακολουθήσουμε το πρίσμα ότι κάθε throw πρέπει να έχει αντίστοιχο catch, μπορείτε να ρυθμίσετε έναν κορυφαίο διαχειριστή εξαιρέσεων για την επεξεργασία λεγμένων σφαλμάτων.

Δημιουργία προσαρμοσμένης κλάσης Exception

Η δημιουργία μιας προσαρμοσμένης διαχείρισης εξαιρέσεων είναι πολύ απλή. Δημιουργούμε απλώς μια ειδική κλάση, η οποία καλείται οι συναρτήσεις της όταν προκύπτει εξαίρεση στο PHP. Η κλάση πρέπει να είναι επέκταση της κλάσης exception.

Η προσαρμοσμένη κλάση exception κληρονομεί όλες τις ιδιότητες της κλάσης exception του PHP, μπορείτε να προσθέσετε προσαρμοσμένες συναρτήσεις.

Ξεκινάμε τη δημιουργία της κλάσης exception:

<?php
class customException extends Exception
 {
 public function errorMessage()
  {
  //error message
  $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile()
  : <b>'.$this->getMessage().'</b> δεν είναι μια έγκυρη διεύθυνση e-mail
  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();
 }
?>

Η νέα κλάση είναι αντιγραφή της παλιάς κλάσης exception, με την προσθήκη της συνάρτησης errorMessage(). Καθώς είναι αντιγραφή της παλιάς κλάσης, αποκτά τις ιδιότητες και τα μεθόδους της παλιάς κλάσης, μπορούμε να χρησιμοποιήσουμε τα μεθόδους της κλάσης exception, όπως getLine(), getFile() και getMessage().

Example explanation:

Το παραπάνω κείμενο κώδικα εκθέτει μια εξαιρετική κατάσταση και την κ捕获 μέσω μιας προσαρμοσμένης κλάσης exception:

  1. The customException() class is created as an extension of the old exception class. This way, it inherits all the properties and methods of the old class.
  2. Δημιουργία της συνάρτησης errorMessage(). Αν η διεύθυνση e-mail δεν είναι έγκυρη, η συνάρτηση επιστρέφει μια μηνύση σφάλματος
  3. Αναθέστε τη μεταβλητή $email σε μη έγκυρη αλφαβητική αλυσίδα διεύθυνσης e-mail
  4. Εκτέλεση του κειμένου κώδικα "try", λόγω της μη έγκυρης διεύθυνσης e-mail, θα εκθέσει εξαιρετική κατάσταση
  5. Το "catch" κείμενο κώδικα κ捕获 την εξαιρετική κατάσταση και εμφανίζει την μηνύση σφάλματος

Πολλαπλές εξαιρετικές καταστάσεις

Μπορείτε να χρησιμοποιήσετε πολλαπλές εξαιρετικές καταστάσεις για ένα κείμενο κώδικα, για να ελέγξετε πολλαπλές περιπτώσεις.

Μπορείτε να χρησιμοποιήσετε πολλαπλά κείμενα κώδικα if..else ή ένα κείμενο κώδικα switch, ή να ενσωματώσετε πολλαπλές εξαιρετικές καταστάσεις. Αυτές οι εξαιρετικές καταστάσεις μπορούν να χρησιμοποιήσουν διαφορετικές κλάσεις exception και να επιστρέψουν διαφορετικές μηνύσεις σφάλματος:

<?php
class customException extends Exception
{
public function errorMessage()
{
//error message
$errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile()
: <b>'.$this->getMessage().'</b> δεν είναι μια έγκυρη διεύθυνση e-mail
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();
 }
?>

Example explanation:

Το παραπάνω κείμενο κώδικα δοκιμάζει δύο συνθήκες, αν καμία από αυτές τις συνθήκες δεν ισχύει, θα εκθέσει μια εξαιρετική κατάσταση:

  1. The customException() class is created as an extension of the old exception class. This way, it inherits all the properties and methods of the old class.
  2. Create the errorMessage() function. If the email address is not valid, the function returns an error message.
  3. Εκτέλεση του κειμένου κώδικα "try", στην πρώτη συνθήκη, δεν θα εκθέσει εξαιρετική κατάσταση.
  4. Κατά την παρουσία της αλφαβητικής αλυσίδας "example" στο e-mail, η δεύτερη συνθήκη θα προκαλέσει την εξαιρετική κατάσταση.
  5. Το "catch" κείμενο κώδικα θα κ捕获 την εξαιρετική κατάσταση και θα εμφανίσει την κατάλληλη μηνύση σφάλματος

Αν δεν έχει προσαρμοστεί η εξαιρετική κατάσταση customException και μόνο η βασική εξαιρετική κατάσταση έχει προσαρμοστεί, θα χειριστείτε την εξαιρετική κατάσταση εκεί.

Επανεκθέτηση εξαιρετικής κατάστασης

Συχνά, όταν εκτεθεί μια εξαιρετική κατάσταση, μπορείτε να θέλετε να την χειριστείτε με έναν τρόπο διαφορετικό από τον τυπικό. Μπορείτε να εκθέσετε ξανά την εξαιρετική κατάσταση σε ένα "catch" κείμενο κώδικα.

The script should hide system errors from the user. While system errors may be important for programmers, users are not interested in them. To make it easier for users, you can throw exceptions again with user-friendly messages:

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

Example explanation:

The above code checks if the string "example" is present in the email address. If it is, it throws the exception again:

  1. The customException() class is created as an extension of the old exception class. This way, it inherits all the properties and methods of the old class.
  2. Create the errorMessage() function. If the email address is not valid, the function returns an error message.
  3. Set the $email variable to a valid email address but containing the string "example".
  4. The "try" block contains another "try" block, allowing the exception to be thrown again.
  5. An exception was triggered because the e-mail contains the string "example".
  6. "catch" caught the exception and re-threw "customException".
  7. Caught "customException" and displayed an error message.

Αν η εξαίρεση δεν συλληφθεί στον τρέχοντα κώδικα try, θα αναζητηθεί σε υψηλότερο επίπεδο για κώδικα catch.

Ρύθμιση κορυφαίου χειριστή εξαιρέσεων (Top Level Exception Handler)

Η συνάρτηση set_exception_handler() μπορεί να ρυθμίσει μια χρήση 定义 συνάρτηση για να χειριστεί όλες τις μη συλληφθείσες εξαιρέσεις.

<?php
function myException($exception)
{
echo "<b>Exception:</b> " , $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
?>

Η έξοδος του παραπάνω κώδικα πρέπει να μοιάζει με κάτι τέτοιο:

Exception: Uncaught Exception occurred

Στο παραπάνω κώδικα δεν υπάρχει κώδικας catch, αλλά προκαλείται η επεξεργασία εξαιρέσεων στο επίπεδο του κορμού. Πρέπει να χρησιμοποιηθεί αυτή η συνάρτηση για να συλληφθούν όλες οι μη συλληφθείσες εξαιρέσεις.

Οι κανόνες των εξαιρέσεων

  • Ο κώδικας που απαιτεί να χειριστεί εξαιρέσεις πρέπει να τοποθετηθεί μέσα στον κώδικα του try, ώστε να μπορεί να συλληφθούν πιθανές εξαιρέσεις.
  • Κάθε κώδικας try ή throw πρέπει να έχει τουλάχιστον έναν αντίστοιχο κώδικα catch.
  • Με τη χρήση πολλαπλών κωδίκων catch μπορεί να συλληφθούν διαφορετικές τύπους εξαιρέσεων.
  • Μπορεί να εκτροχιάσει ξανά (re-thrown) η εξαίρεση μέσα από τον κώδικα του catch του try.

Με απλά λόγια: Αν προκύψει εξαίρεση, πρέπει να την αντιμετωπίσει.