Saturday, March 12, 2011

PHP: Your exception classes

Exceptions

This article is the second part of PHP Exception articles. In the previous one, I've written about Exceptions, I've showed you the basic usage and I've provided some examples. It won't be different this time, but I'm going to be a little more advanced. This article is about how to write your own classes.

Reminder: Exception is a special condition that changes the normal flow of the code.


Extending exceptions

You can extend the core exception class in PHP to have your own class which will suit for the given tasks ahead. It's a good way for categorisation of errors. What I mean is, you can make input exceptions, error exceptions, email exceptions. Another example is if you use the MVC programming pattern, you can make classes related to each layer as follows: ModelException, ViewException, ControllerException. After this, you can extend more classes depending on the occuring errors in each layer.

But let's return from programming patterns to the example code below. Take a look at it. :)

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<?php

 class InputException extends Exception {};

 class SomethingBadException extends Exception {};

 class SomethingReallyBadException extends Exception {};


 // ...

 class foo {

  // ...

  function let_it_happen($input) {

   if( !validate_input($input) ) {

    throw new InputException('Invalid input given.');

   }


   if( !calculate_something($input) ) {

    throw new SomethingBadException('Something bad happenned.');

   } else
   {

    if( !generate_something($input) ) {

     throw new SomethingReallyBadException('Something really terrible happened.');

    }

   }

   // ...

  }

  // ...

 }


 // later in the code...

 $bar = new foo();

 try {


  $bar->let_it_happen();


 }
 catch (InputException $e) {

  echo 'Input error: '.$e->getMessage();

  // do something here, like logging
  log('Error: '.$e->getMessage());

 }
 catch (SomethingBadExcpetion $e) {

  echo 'Error: '.$e->getMessage();

  log('Error: '.$e->getMessage());

  handle_some_stuff();


 }
 catch (SomethingReallyBadException $e) {

  echo 'Fatal error: '.$e->getMessage();

  log('Fatal error: '.$e->getMessage());

  $email->notify_admin('www.site.com - problem',"The following thing happened: ".$e->getMessage()."\n Log in immediately.");

 }


?>

I've defined three new exceptions, and I've also written a class where these exceptions appear. Notice the multiple catch blocks. You have to catch all kind of exceptions by making catch blocks for each of the classes. If an exception occurs you can make the necessary steps in each of the blocks to set variables, warn the user, log or notify someone.

You can also add your custom properties and methods to an extended class. But be careful with this! I say this because if you add a method to your exception class that uses an object - for example email - and you throw this exception in a context where that object is not available or currently not loaded, you're shot and you can start debugging and hacking. Please, prevent this and design your application correctly. The code:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php  
 
 class BadBadException extends Exception {
  
  private $__variable;
  
  function set_variable($in) {
   
   $this->__variable = $in;
   
  }
  
  function get_variable() {
   
   return $this->__variable;
   
  }
  
  function handleBadException() {
   
   log($this->getMessage());
   
   do_something_necessary();
   
  }
  
 }
 
 // ...
 
 try {
  
  throw new BadBadException('bad bad message');
  
 } 
 catch (BadBadException $e) {
  
  echo $e->getMessage();
  
  $e->handleBadException();
  
 }
 

?>

Final words

Deciding to use exceptions is a good start to make your application more logical, more understandable and what is much more important, more flexible.

Zsolt Szivák

No comments:

Post a Comment