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

Monday, March 7, 2011

Javascript: validating object interfaces

The interface is one of the most used tool in object-oriented programming. Based on the Gang of Four’s Design Patterns book, it is the first principle of reusable OOP. Unfortunately Javascript can’t implement any interfaces. At least not the usual way. And that’s where my interface class comes in. :)

I got the basic idea from the book Pro Javascript Design Patterns [Apress]. The authors have mentioned three types of emulating an interface in Javascript.

  1. Comments:
    "The easiest and least effective way of emulating an interface is with comments. Mimicking the style of other object-oriented languages, the "interface" and "implements" keywords are used but are commented out so they do not cause syntax errors."
  2. Attribute checking:
    A bit better, but it can be easily tricked out by a careless programmer. In this method when creating a class, it is left to the programmer's conscience to decide which interface is implemented. The interface name is stored in an array. Then, when an interface check is required, a function is validating the content of this array. If it says the class is implementing the given interface, the function believes it and the program flow continues.
    Personally, I don’t really like this method.
  3. Duck typing:
    This is where I have had my inspiration :) There is a line in the book, I'm always smiling when I'm reading it: "Duck typing was named after the saying, 'If it walks like a duck and quacks like a duck, it's a duck.' " :)
    Well, I was quite satisfied with this solution. However the example, that the authors were providing is only checking, if the object has the given methods defined.

My improved interface class:

So I decided to improve this Duck typing method, and add some additional functionality. With my interface class, instead of just checking the methods of the class (or object), we can:
  • check variable and method existence
  • check method’s parameters
  • check method return value
  • check variable value
  • define callback error handling function
  • and we can even define own interface functions, to validate the internal state of the object.
It's quite exciting :)

Here is a brief explanation, of how is this class used:
1.) Define an interface:
1
2
3
4
5
var exampleInterface = new Interface("example", { 
   /* requirements*/
}, {
   /* functions called on error */
})

2.) Create your object

3.) Validate the object's state: by passing the validated object and the interface objects as parameters
1
Interface.check( /* object to validate */, /* interface object */[...]);


Let's see some comment-explained code. First, here are some example interfaces defined:

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
// defined interfaces to implement
// checks all these variables. They have to be defined.
var InterfaceVariables = new Interface('InterfaceVariables', {

   // checks, if it is true
   isBooleanVal: true, 

   // just check the variable if it is defined
   isNullVal: null,

   // this string has to contain this value
   stringVal: 'required string value',

   // variable check with interface function. In this example, a variable has to be greater than one. It must always have a bool return.
   isGreaterThanOne: function(obj) { 
      return obj.isGreaterThanOne > 1;
   },

   // array check. here are other items not allowed
   allowJustThese: ['item1', 'item2', 'item3'],

   // array check. other items are allowed
   theseAreRequired_butOthersAllowedToo: ['item1', 'item2', 'item3', ".."],


}, {
   // this object contains the error handling functions

 
   // this runs only if the isBooleanVal is not true
   isBooleanVal: function (intf, obj) {alert("isBooleanVal is not true. Required interface: "+intf.name+".");},

   // and this runs only if the stringVal value is not the required one.
   stringVal: function (intf, obj) {alert("stringVal value is not valid. Required interface: "+intf.name+".");}

});

var InterfaceMethods = new Interface('InterfaceMethods', {

   // checks if method has only these two params. if others are also enabled, put ".." in the end
   // ret: boolean      checks method's return value. Params: (expected return [, arg1, arg2, ...] )
   methodParamCheckAndReturnCheck: {
      args: ['num1', 'num2'], 
      ret: [12, 2, 3] 
   },

   // i think this is clear
   // method must not have parameters
   // ret: true      expected return value is 6
 methodNoParamAndReturnsSix: { 
      args: [],
      ret: 6
   },

   // checks if this is a function plus the parameters
   checkMethodParams: ['arg1', 'arg2', '..'],

   // just check function existence
   isFunctionDefined: null,

   // no parameters allowed
   isFunctionWithNoParams: [] 

},{
   methodNoParamAndReturnsSix: function (intf, obj) { alert("Error with method: methodNoParamAndReturnsSix. Interface: "+intf.name+"."); }
});


For example in the first interface I defined only variable's, and in the second one the methods' rules. Staying at the example, here is a class which "implements" these interfaces:

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
// class that has to implement the interface
var classToImplementInterface = (function() {

   // this variable should be true, so the interface callback function will be called
   this.isBooleanVal = false;
   this.isNullVal = null;
   this.stringVal = "required string value";
   this.isGreaterThanOne = 2;

   var privateVar = 'private'; // just for fun... (a class' interface is its public variables and methods, if you wouldn't know that :) )
   var privateMultiplyer = 2;

   this.methodParamCheckAndReturnCheck = function(num1, num2) {
      return num1 * num2 * privateMultiplyer;
   }

   // this method should return 6. So this will generate an error.
   this.methodNoParamAndReturnsSix = function() {
      return 5;
   }

   this.allowJustThese = Array('item1', 'item2', 'item3');
   this.theseAreRequired_butOthersAllowedToo = Array('item1', 'item2', 'item3', "item4", "item5");

   this.checkMethodParams = function (arg1, arg2, arg3) {}

   this.isFunctionDefined = function ( can, have, params ) {}

   this.isFunctionWithNoParams = function () {} // must not have params


 
})


And here is, how you can evaluate the rules:

1
2
3
4
5
6
7
/////////////////////////////////////////////////////////////////////
//       CONCRETE OBJECT to IMPLEMENT INTERFACES
/////////////////////////////////////////////////////////////////////
var concreteObject = new classToImplementInterface();

// before doing something validate object's interface
Interface.check(concreteObject, InterfaceVariables, InterfaceMethods);


A concrete example:

Let's say, there is a car class. A method is called which is responsible for moving objects on the canvas, and the car object is passed in as a parameter. However, to move that car, there are some object requirements. For example, is someone driving it? Or is the door closed?. These can be solved with variable checking. Then…has the given car object all the methods which are used later on? Or is the body state higher than 10%? This can be solved with an anonym function. These requirements must be satisfied for error-free run.


Well that's it. I'm quite satisfied with the results. It's small and simple. Probably it will be used only in development phase, so I haven't done any speed optimization.

If you are interested in further development, please let me know!

Source files:

  • index.html
  • interface.js
  • interface.min.js
  • functions.js

Download:




I'm very enthusiastic and appreciate every donation. I will spend the full amount on books, to improve my skills and create more projects like this (and even better).

Thanks,
Phil



Changelog


  • 1.1:
    • Added callback functionality
    • Callback parameters: ( interface object, checked object )
  • 1.0:
    • variable and method existence
    • method's parameters
    • method return value
    • variable value
    • and we can even define own interface functions, to validate the internal state of the object.

Saturday, March 5, 2011

PHP: Exceptions in action

How to handle errors in the code flow?

Object oriented programming offers a useful way to get through this problem. When you come across a condition where you must generate an error (when checking inputs at form validation for example), you can throw an exception. See the example below:

  • /* a function what will throw an exception if the $input is invalid */
  • function check_input($input=NULL) {
  • if( !is_string($input) ) throw new Exception('Invalid input',1);
  • }
  •  
  •  
  • /* later in the code */
  • try {
  • /* it will throw an exception */
  • check_input(4);
  • check_input('hi there');
  • }
  • catch (Exception $e) {
  • echo $e->getMessage();
  • }

When using exceptions, your code must contain the following things:
  • a try {} block: this is where you trigger the exception
  • a throw new Exception() call: this is how you trigger the exception
  • one or more catch() {} blocks: this is where you handle the exception.
The check_input() function will throw an exception if it is called with a non-string parameter. I've called it twice in the try block. If an exception is thrown, the code flow stops running inside the try block. This is where the catch block becomes important, because this is where the code continues running if there is a corresponding catch block for the thrown exception class.The $e variable will be our exception object and we can get the values from it. If you wish to see the default class for exception objects, please visit the PHP Exception manual. Initialize an exception as follows:

  • throw new Exception('Your message', <your integer number>);

Let me extend our first example:

  • /* a function what will throw an exception if the $input is invalid */
  • function check_input($input=NULL) {
  • if( !is_string($input) ) throw new Exception('Invalid input',1);
  • if( strlen($input)>10 ) throw new Exception('Too long input',2);
  • }
  •  
  •  
  • /* later in the code */
  • try {
  • /* it will throw an exception */
  • check_input(4);
  • }
  • catch (Exception $e) {
  • echo $e->getMessage();
  • switch( $e->getCode() ) {
  • case 1:
  • {
  • /* do something here for code 1 */
  • /* let's just echo the message */
  • echo $e->getMessage();// 'Invalid input'
  • } break;
  • case 2:
  • {
  • /* do something else here for code 2 */
  • /* echo the error message and something else */
  • echo $e->getMessage();// 'Too long input'
  • echo 'Give a shorter string.';
  • } break;
  • default:
  • {
  • /* do something default here */
  • } break;
  • }
  • }

In the extended example, I modified the code to throw another exception if another condition is met. Note that there is two exception and one catch block. The reason why I can do this in the code is because we handling one exception class called Exception. PHP has another default Exception class called ErrorException. If you wish to use different exception classes in your code, you must have a corresponding catch block for them. (You can read about this in my next article.)

When I constructed the exception objects, I gave them different codes in the second parameter. By the $e->getCode() method, you can get the corresponding code for the exception object and for example, you can put it to a switch-case statement where each case handles a separate error.

Note that if you throw an exception without putting it into a try block, your code ends in a fatal error.

In my next article I'm going to write about how to extend the default Exception class and how to write your own classes for handling errors rather then using switch statements.

I hope I've helped.

Zsolt Szivák